码迷,mamicode.com
首页 > 系统相关 > 详细

Linux系统开发 4 进程资源 环境 fork()子进程 wait() waitpid()僵尸 孤儿进程

时间:2016-08-06 07:08:52      阅读:484      评论:0      收藏:0      [点我收藏+]

标签:linux系统开发 4 进程资源 环境 fork()子进程 wait() waitpid()僵尸 孤儿进程




《大纲》
Linux系统编程
	进程资源上限
	进程环境变量
	进程获取/修改环境变量
	创建子进程fork()
	最大进程数测试
	程序的设置用户ID/组ID/黏住位
	exec簇函数,执行程序覆盖堆栈
	fork 与execl函数在一起
	exec() 与主程序同一个PCB
	僵尸进程
	wait()回收僵尸进程
	证明:父子进程同组pid
	waitpid() 非阻塞等待子线程发生变化
	孤儿进程演示【父进程已经结束,子进程还在运行】	
	


进程资源上限值

chunli@ubuntu16:~$ cat /proc/self/limits 
Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        0                    unlimited            bytes     
Max resident set          unlimited            unlimited            bytes     
Max processes             3749                 3749                 processes 
Max open files            1024                 65536                files     
Max locked memory         65536                65536                bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       3749                 3749                 signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    
Max realtime timeout      unlimited            unlimited            us        
chunli@ubuntu16:~$



进程获取环境变量

chunli@ubuntu16:~/linux_c$ cat main.c 
#include <stdio.h>
int main(int num,char **args,char **env)
{
	int i = 0;
	for(i = 0;env[i] != NULL;i++)	
	{
		printf("%s\n",env[i]);
	}
	return 0;
}

chunli@ubuntu16:~/linux_c$ gcc main.c  && ./a.out 
XDG_SESSION_ID=8
TERM=xterm
SHELL=/bin/bash
SSH_CLIENT=10.11.12.1 2826 22
SSH_TTY=/dev/pts/9
USER=chunli
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
MAIL=/var/mail/chunli
PATH=/home/chunli/bin:/home/chunli/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
QT_QPA_PLATFORMTHEME=appmenu-qt5
PWD=/home/chunli/linux_c
LANG=zh_CN.UTF-8
SHLVL=1
HOME=/home/chunli
LANGUAGE=zh_CN:zh
LOGNAME=chunli
SSH_CONNECTION=10.11.12.1 2826 10.11.12.21 22
LESSOPEN=| /usr/bin/lesspipe %s
XDG_RUNTIME_DIR=/run/user/1000
LESSCLOSE=/usr/bin/lesspipe %s %s
_=./a.out
OLDPWD=/home/chunli
chunli@ubuntu16:~/linux_c$



getenv(),setenv()获取修改进程的环境变量

chunli@ubuntu16:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
int main(int num,char **args,char **env)
{
	printf("PATH=%s\n", getenv("PATH"));
	setenv("PATH","Hello World!",1);
	printf("PATH=%s\n", getenv("PATH"));
	return 0;
}

chunli@ubuntu16:~/linux_c$ gcc main.c  && ./a.out 
PATH=/home/chunli/bin:/home/chunli/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
PATH=Hello World!
chunli@ubuntu16:~/linux_c$



fork()进程创建

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int num,char **args,char **env)
{
	int i = 0;	//变量,读时共享,写时复制.把子进程需要的变量才复制到子进程一份
	printf("主函数\n");
	pid_t  pid;
	pid = fork();	//子父进程诞生,从下面的语句开始运行,不再运行本条及上面的语句
			//子进程,仅仅是pid不一样,开始执行语句的位置也不一样
	if(pid > 0)
	{
		while(1)
		{
			printf("父进程 %d \n",i++);	//共享变量,读共享,写操作才会复制一份
			printf("父进程的pid =%d \n",getpid());
			printf("父进程的ppid =%d \n",getppid());
			sleep(5);
		}
	}
	else if(pid == 0)
	{
		while(1)
		{
			printf("子进程 %d \n",i++);
			printf("子进程的pid =%d \n",getpid());
			printf("子进程的ppid =%d \n",getppid());
			sleep(2);
		}
	}
	else
	{
		printf("进程创建失败\n");
	}
	return 0;
}

chunli@ubuntu:~/linux_c$ 

chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out 
主函数
父进程 0 
父进程的pid =6189 
父进程的ppid =5811 
子进程 0 
子进程的pid =6190 
子进程的ppid =6189 
子进程 1 
子进程的pid =6190 
子进程的ppid =6189 
子进程 2 
子进程的pid =6190 
子进程的ppid =6189 
父进程 1 
父进程的pid =6189 
父进程的ppid =5811 
子进程 3 
子进程的pid =6190 
子进程的ppid =6189 
^C


测试最多能开启线程数

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int num,char **args,char **env)
{
	int time = 50;	//让子进程存活n 秒
	int n = 0;
	pid_t pid;
	while(1)
	{
		pid = fork();
		if(pid == 0)
		{
			break;	//如果是子进程,就跳出来
		}
		if(pid < 0)
		{
			printf("\nfork 出错\n");
			exit(1);
		}
		//printf("%d\t",n++);	//如果启用这一句,会执行两次输出
		printf("%d\n",n++);
	}
	while(time--)
	{
		sleep(1);	//子进程干的事儿
		//printf(".");
	}
	
	return 0;
}

chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out
...............................
3735
3736
3737

fork 出错




设置用户ID,执行文件时以文件所有者运行

比如passwd命令,普通用户执行这个命令,修改的密码放在/etc/shadow文件中,

只有root权限才可以修改文件的内容

chunli@ubuntu:~$ which passwd 
/usr/bin/passwd
chunli@ubuntu:~$ ls -l /usr/bin/passwd 
-rwsr-xr-x 1 root root 54256 3月  29 17:25 /usr/bin/passwd
chunli@ubuntu:~$ 
chunli@ubuntu:~$ ls -l /etc/shadow
-rw-r----- 1 root shadow 1273 8月   2 19:19 /etc/shadow


文件所属chunli,chuli来运行,没问题

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(int num,char **args,char **env)
{
	int fd = 0;
	fd = open("./abc",O_CREAT,0644);//如果没有这个文件就创建
	if(fd == -1)
	{
		perror("文件打开/创建\n");
	}
	printf("运行程序的实际用户id是%d\n",getuid());
	printf("运行程序的有效用户id是%d\n",geteuid());

	return 0;
}

chunli@ubuntu:~/linux_c$ 


gcc main.c  && ./a.out 
运行程序的实际用户id是1000
运行程序的有效用户id是1000
chunli@ubuntu:~/linux_c$ ll
总用量 16K
-rw-r--r-- 1 chunli chunli    0 8月   5 11:31 abc
-rwxrwxr-x 1 chunli chunli 8.7K 8月   5 11:31 a.out*
-rw-rw-r-- 1 chunli chunli  456 8月   5 11:30 main.c


把上面的可执行程序放在根目录,无法创建文件

chunli@ubuntu:~/linux_c$ cp ./a.out  /
cp: 无法创建普通文件‘/a.out‘: 权限不够
chunli@ubuntu:~/linux_c$ sudo cp ./a.out  /
[sudo] chunli 的密码: 
chunli@ubuntu:~/linux_c$ ll /a.out 
-rwxr-xr-x 1 root root 8.7K 8月   5 11:32 /a.out*
chunli@ubuntu:~/linux_c$ 
chunli@ubuntu:/$ cd /
chunli@ubuntu:/$ ./a.out 
文件打开/创建: Permission denied
运行程序的实际用户id是1000
运行程序的有效用户id是1000



设置用户ID,程序运行时以root身份运行,可以创建文化

技术分享



chunli@ubuntu:/$ sudo chmod  4611 a.out 
chunli@ubuntu:/$ ll a.out 
-rwS--x--x 1 root root 8.7K 8月   5 11:34 a.out*
chunli@ubuntu:/$ ./a.out 
运行程序的实际用户id是1000
运行程序的有效用户id是0
chunli@ubuntu:/$ ll abc 
-rw-r--r-- 1 root chunli 0 8月   5 11:37 abc




设置用户id和组ID
chunli@ubuntu:/$ sudo chmod  6611 a.out 
chunli@ubuntu:/$ ll a.out
-rwS--s--x 1 root root 8.7K 8月   5 11:34 a.out*
chunli@ubuntu:/$ 

还有一个粘住位,常驻内存程序
chunli@ubuntu:/$ sudo chmod  7777 a.out 
chunli@ubuntu:/$ ll a.out
-rwsrwsrwt 1 root root 8.7K 8月   5 11:34 a.out*
chunli@ubuntu:/$



exec簇函数

#include <unistd.h>

extern char **environ;

int execl(const char *path, const char *arg, ...
	       /* (char  *) NULL */);
int execlp(const char *file, const char *arg, ...
	       /* (char  *) NULL */);
int execle(const char *path, const char *arg, ...
	       /*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],
	       char *const envp[]);


execl执行一个程序,完全替换掉当前程序的堆栈

exec下面的语句没有机会执行了

chunli@ubuntu:~/linux_c$ ll
总用量 16K
-rwxrwxr-x 1 chunli chunli 8.5K 8月   5 11:56 a.out*
-rw-rw-r-- 1 chunli chunli  277 8月   5 11:56 main.c
chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(int num,char **args,char **env)
{
	printf("Hello \n");
	execl("/bin/ls","ls","-l",NULL);//下面的代码没有机会执行,程序从ls返回
	printf("World \n");
	return 0;
}

chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out 
Hello 
总用量 16
-rwxrwxr-x 1 chunli chunli 8656 8月   5 11:56 a.out
-rw-rw-r-- 1 chunli chunli  277 8月   5 11:56 main.c
chunli@ubuntu:~/linux_c$



证明:execl函数下面的代码没有机会执行

chunli@ubuntu:~/linux_c$ cat test.c 
int main()
{
	return 9;	//测试程序,返回值是9
}
chunli@ubuntu:~/linux_c$ gcc test.c  -o test

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(int num,char **args,char **env)
{
	printf("Hello \n");
	execl("/home/chunli/linux_c/test","./test",NULL);
	printf("World \n");
	return 0;
}

chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out 
Hello 
chunli@ubuntu:~/linux_c$ echo $?
9



fork() execl()在一起演示

子进程加载其他程序,替换当前的程序代码段

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(int num,char **args,char **env)
{
	pid_t pid  = fork();
	if(pid == 0 )
	{
		execl("/usr/bin/firefox","firefox","www.baidu.com",NULL);//参数1,2,3
	}
	if(pid > 0)
	{
		printf("I‘m parent \n");
		sleep(1);
	}
	if(pid < 0)
	{	
		perror("fork");
		exit(2);
	}
	return 0;
}

chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out 
I‘m parent 
Error: GDK_BACKEND does not match available displays
chunli@ubuntu:~/linux_c$


execlp在PATH里面找可执行程序

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(int num,char **args,char **env)
{
	pid_t pid  = fork();
	if(pid == 0 )
	{
		execlp("ls","ls","-lh",NULL);//参数1,2,3
	}
	if(pid > 0)
	{
		printf("I‘m parent \n");
		sleep(1);
	}
	if(pid < 0)
	{	
		perror("fork");
		exit(2);
	}
	return 0;
}

chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out 
I‘m parent 
总用量 32K
-rwxrwxr-x 1 chunli chunli 8.7K 8月   5 13:47 a.out
-rw-rw-r-- 1 chunli chunli  396 8月   5 13:47 main.c
-rwxrwxr-x 1 chunli chunli 8.4K 8月   5 12:04 test
-rw-rw-r-- 1 chunli chunli   26 8月   5 12:04 test.c
chunli@ubuntu:~/linux_c$


execvp()函数,指针数组的形式

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(int num,char **args,char **env)
{
	char *str[]={"ls","-l",NULL};
	pid_t pid  = fork();
	if(pid == 0 )
	{
		execvp("ls",str);//参数1,2,3
	}
	if(pid > 0)
	{
		printf("I‘m parent \n");
		sleep(1);
	}
	if(pid < 0)
	{	
		perror("fork");
		exit(2);
	}
	return 0;
}

chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out 
I‘m parent 
总用量 32
-rwxrwxr-x 1 chunli chunli 8920 8月   5 13:55 a.out
-rw-rw-r-- 1 chunli chunli  415 8月   5 13:55 main.c
-rwxrwxr-x 1 chunli chunli 8552 8月   5 12:04 test
-rw-rw-r-- 1 chunli chunli   26 8月   5 12:04 test.c
chunli@ubuntu:~/linux_c$


execle()不仅把代码堆栈替换,还把命令行参数环境变量也替换

exec() 与主程序同一个PCB【看图】

技术分享

chunli@ubuntu:~/linux_c$ cat test.c 
#include <stdio.h>
#include <ctype.h>
int main()
{
	int ch = 0;
	while((ch = getchar()) != EOF)
	{
		putchar(toupper(ch));
	}
	return 0;
}
chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(int argc,char **args,char **env)
{
        int fd = 0;
        if(argc < 2)
        {
                fputs("需要1个参数\n",stdout);
                exit(1);
        }
        fd = open(args[1],O_RDONLY);    //fd = 3,指向了文件结构体
        if(fd < 0)
        {
                perror("open");
                exit(1);
        }
        dup2(fd,STDIN_FILENO);  //关闭了标准输入,fd就是0
        close(fd);              //关闭文件描述符与文件结构体的关系
        execl("./upper","upper",NULL);  //execl的程序与主程序公用PCB,PCB里面有文件描述符表
                                        //upper里面的getchar操作从文件描述符为0的文件读内容
        perror("exec ./upper");
        exit(2);
        return 0;
}

chunli@ubuntu:~/linux_c$ 

chunli@ubuntu:~/linux_c$ gcc test.c -o upper
chunli@ubuntu:~/linux_c$ gcc main.c -o main
chunli@ubuntu:~/linux_c$ ./main 
需要1个参数
chunli@ubuntu:~/linux_c$ gcc main.c && ./main main.c 
#INCLUDE <STDIO.H>
#INCLUDE <STDLIB.H>

#INCLUDE <SYS/TYPES.H>
#INCLUDE <SYS/STAT.H>
#INCLUDE <FCNTL.H>
#INCLUDE <UNISTD.H>
#INCLUDE <ERRNO.H>

INT MAIN(INT ARGC,CHAR **ARGS,CHAR **ENV)
{
	INT FD = 0;
	IF(ARGC < 2)
	{
		FPUTS("需要1个参数\N",STDOUT);
		EXIT(1);
	}
	FD = OPEN(ARGS[1],O_RDONLY);	//FD = 3,指向了文件结构体
	IF(FD < 0)
	{
		PERROR("OPEN");
		EXIT(1);
	}
	DUP2(FD,STDIN_FILENO);	//关闭了标准输入,FD就是0
	CLOSE(FD);		//关闭文件描述符与文件结构体的关系
	EXECL("./UPPER","UPPER",NULL);	//EXECL的程序与主程序公用PCB,PCB里面有文件描述符表
					//UPPER里面的GETCHAR操作从文件描述符为0的文件读内容
	PERROR("EXEC ./UPPER");
	EXIT(2);
	RETURN 0;
}

chunli@ubuntu:~/linux_c$



僵尸进程 演示

在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他, 

那么他将变成一个僵尸进程。

子进程运行结束,内核PCB并没有被释放,等待回收

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int num,char **args,char **env)
{
	pid_t  pid;
	pid = fork();
	if(pid > 0)
	{
		while(1)
			sleep(5);
	}
	return 0;
}

chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out



chunli     5908  0.0  0.0   4224   656 pts/1    S+   15:06   0:00 ./a.out
chunli     5909  0.0  0.0      0     0 pts/1    Z+   15:06   0:00 [a.out] <defunct>
chunli     5913  0.0  0.3  44432  3176 pts/21   R+   15:06   0:00 ps aux


wait()回收僵尸进程

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int num,char **args,char **env)
{
	pid_t  pid;
	pid_t  pid_c;
	pid = fork();
	if(pid > 0)
	{
		while(1)
		{
			printf("I‘m parent %d\n",getpid());
			pid_c = wait(NULL);	//阻塞函数,等待子进程死
			printf("wait for child %d\n",pid_c);
			sleep(5);
		}
	}
	else if(pid == 0)
	{
		printf("I‘m child %d\n",getpid());
		sleep(2);
	}
	return 0;
}

chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out
I‘m parent 6265
I‘m child 6266
wait for child 6266
I‘m parent 6265
wait for child -1
I‘m parent 6265
wait for child -1
^C
chunli@ubuntu:~/linux_c$ 


chunli     6104  0.0  0.0   4356   744 pts/1    S+   16:03   0:00 ./a.out
chunli     6108  0.0  0.3  44432  3224 pts/21   R+   16:03   0:00 ps aux



证明:父子进程同组pid

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int num,char **args,char **env)
{       
        int i = 4;
        pid_t  pid;
        pid_t  pid_c;
        while(i--)
        {       
                pid = fork();
                if(pid == 0)
                {
                        break;
                }
        }       
        if(pid > 0)
        {       
                printf("I‘m parent %d\n",getpid());
                wait(NULL);
                sleep(30);
        }
        if(pid == 0)
        {
                printf("I‘m child %d\n",getpid());
                sleep(3);
        }
        return 0;
}

编译运行:
chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out
I‘m parent 6416
I‘m child 6420
I‘m child 6419
I‘m child 6417
I‘m child 6418

chunli@ubuntu:~/linux_c$ ps ajx 
  PPID    PID   PGID    SID TTY       TPGID STAT   UID   TIME COMMAND
  5242   6433   6433   5242 pts/1      6433 S+    1000   0:00 ./a.out
  6433   6434   6433   5242 pts/1      6433 S+    1000   0:00 ./a.out
  6433   6435   6433   5242 pts/1      6433 S+    1000   0:00 ./a.out
  6433   6436   6433   5242 pts/1      6433 S+    1000   0:00 ./a.out
  6433   6437   6433   5242 pts/1      6433 S+    1000   0:00 ./a.out
  5673   6438   6438   5673 pts/21     6438 R+    1000   0:00 ps ajx

  
可以看出,PGID都是一样
chunli@ubuntu:~/linux_c$ man 2 wait
< -1   meaning wait for any child process whose process group ID is equal to the absolute value of pid.
从这句话意思
chunli@ubuntu:~/linux_c$ kill -9 6433
chunli@ubuntu:~/linux_c$ ps ajx  | grep a.out
chunli@ubuntu:~/linux_c$ 
全部杀干净了

waitpid() 非阻塞等待子线程发生变化

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int num,char **args,char **env)
{
	int i = 3;
	pid_t  pid;
	pid_t  pid_c;
	while(i--)
	{
		pid = fork();
		if(pid == 0)
		{
			break;
		}
	}
	if(pid > 0)
	{
		i = 0;
		while(1)
		{
			sleep(1);
			printf("I‘m parent %d\n",getpid());
			pid_c = waitpid(0,NULL,WNOHANG);	//非阻塞,子进程状态发生改变也会有返回值
								//如果子进程没有发生变化返回0
								//如果子进程发生改变返回子进程的pid
			if(pid_c == -1)
			{
				continue;
			}
			else if(pid_c == 0)
			{
				printf("子进程的状态没有发生变化 %d \n",pid_c);	//如果子进程没有发生变化返回0
			}
			else if(pid_c > 0)
			{
				printf("子进程的状态发生变化 %d \n",pid_c);	//如果子进程没有发生变化返回0
			}
			//sleep(1);	//邪门呀,sleep放在这里一直刷屏
		}
	}
	if(pid == 0)
	{
		printf("I‘m child %d\n",getpid());
		sleep(6);
	}
	return 0;
}
//	pid_t waitpid(pid_t pid, int *status, int options);
//	wait for process to change state
//	< -1   meaning wait for any child process whose process group ID is equal to the absolute value of pid.
//	-1     meaning wait for any child process.
//	0      meaning wait for any child process whose process group ID is equal to that of the calling process.
//	> 0    meaning wait for the child whose process ID is equal to the value of pid.
//	The value of options is an OR of zero or more of the following constants:

//	RETURN VALUE
//	waitpid(): on success, returns the process ID of the child whose state has changed; 
//	if WNOHANG was specified and one or more child(ren) specified by  pid  exist,
//	but have not yet changed state, then 0 is returned.  On error, -1 is returned.



chunli@ubuntu:~/linux_c$ gcc main.c  && ./a.out
I‘m child 7004
I‘m child 7006
I‘m child 7005
I‘m parent 7003
子进程的状态没有发生变化 0 
I‘m parent 7003
子进程的状态没有发生变化 0 
I‘m parent 7003
子进程的状态没有发生变化 0 
I‘m parent 7003
子进程的状态没有发生变化 0 
I‘m parent 7003
子进程的状态没有发生变化 0 
I‘m parent 7003
子进程的状态发生变化 7004 
I‘m parent 7003
子进程的状态发生变化 7005 
I‘m parent 7003
子进程的状态发生变化 7006 
I‘m parent 7003
I‘m parent 7003
I‘m parent 7003
I‘m parent 7003
^C
chunli@ubuntu:~/linux_c$


孤儿进程演示【父进程已经结束,子进程还在运行】

chunli@ubuntu:~/linux_c$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int num,char **args,char **env)
{
	int i = 3;
	pid_t  pid;
	pid_t  pid_c;
	while(i--)
	{
		pid = fork();
		if(pid == 0)
		{
			break;
		}
	}
	if(pid > 0)
	{
		printf("我是父进程 %d\n",getpid());
		exit(1);
	}
	else if(pid == 0)
	{
		i = 100;
		while(i--)
		{
			sleep(1);
			printf("我是子进程 %d 我的父进程是%d\n",getpid(),getppid());
		}
	}
	else
	{
		perror("fork ");
		exit(1);
	}
	return 0;
}
chunli@ubuntu:~/linux_c$ 

编译运行:
chunli@ubuntu:~/linux_c$ gcc main.c -omain && ./main 
我是父进程 4757
chunli@ubuntu:~/linux_c$ 我是子进程 4760 我的父进程是1
我是子进程 4759 我的父进程是1
我是子进程 4758 我的父进程是1
我是子进程 4760 我的父进程是1
我是子进程 4759 我的父进程是1
我是子进程 4758 我的父进程是1
我是子进程 4760 我的父进程是1
我是子进程 4759 我的父进程是1

chunli@ubuntu:~$ ps ajx
  PPID    PID   PGID    SID TTY       TPGID STAT   UID   TIME COMMAND
 4803   4804   4804   4804 pts/9      4804 Ss+   1000   0:00 -bash
     1   4826   4825   4804 pts/9      4804 S     1000   0:00 ./a.out
     1   4827   4825   4804 pts/9      4804 S     1000   0:00 ./a.out
     1   4828   4825   4804 pts/9      4804 S     1000   0:00 ./a.out
  4699   4829   4829   4699 pts/10     4829 R+    1000   0:00 ps ajx

只有结束组pid这么干了  
chunli@ubuntu:~$ kill -9 -4825



本文出自 “魂斗罗” 博客,请务必保留此出处http://990487026.blog.51cto.com/10133282/1834893

Linux系统开发 4 进程资源 环境 fork()子进程 wait() waitpid()僵尸 孤儿进程

标签:linux系统开发 4 进程资源 环境 fork()子进程 wait() waitpid()僵尸 孤儿进程

原文地址:http://990487026.blog.51cto.com/10133282/1834893

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!