之前讲过,子进程退出,父进程如果不管不顾,就可能造成僵尸进程的问题,进而造成内存泄漏。
另外,一旦一个进程变成僵尸状态,那就刀枪不入,“杀人不咋眼”的kill -9也无能为力,因为谁也没有办法杀死一个已经死去的进程。
最后,父进程派给子进程的任务完成的如何,我们需要知道,如,子进程运行完成,结果对还是不对或者是否正常退出。
父进程通过进程等待的方式,回收子进程的资源,获取子进程退出信息。
wait方法
#include
#include
pid_t wait(int* status);
返回值:成功,返回被等待进程pid,失败返回-1;
参数:输出型参数,获取子进程退出状态,
waitpid方法
pid_t waitpid(pid_t pid,int* status,int options);
返回值:
当正常返回的时候waitpid返回收集到的子进程的进程ID;
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
如果调用中出错,则返回-1,这时,errno会被设置成相应的值以指示错误所在;
参数:pid:
pid=-1,等待任一个子进程,与wait等效
pid>0,等待其进程ID与pid相等的子进程
status:
WIFEXITED(status);若为正常终止子进程返回的状态,则为真。(查看进程是否正常退出)
WEXITSTATUS(status);若WIFEXITED非零,提取子进程的退出码。(查看进程的退出码)
options:
默认为0,表示阻塞等待
WNOHANG(非阻塞式等待):若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则放回该子进程的ID。
waitpid(-1,NULL,0) = wait(NULL);
#include 2 #include 3 #include 4 #include 5 #include 6 int main()7 {8 pid_t id = fork();9 if(id<0)10 {11 perror("fork");12 exit(1);//标识进程运行完毕,结果不正确13 }14 else if(id == 0)15 {16 //子进程17 int cnt = 5;18 while(cnt)19 {20 printf("cnt:%d,我是子进程,pid:%d,ppid:%d\n",cnt,getpid(),getppid());21 cnt--;22 }23 exit(54);24 }25 else 26 {27 //父进程28 printf("我是父进程,pid:%d,ppid:%d\n",getpid(),getppid());29 // pid_t ret = wait(NULL);//阻塞式等待30 int status = 0;31 pid_t ret = waitpid(id,&status,0);//阻塞式等待 等待5s//pid_t ret = waitpid(id,&status,WNOHANG);//非阻塞式等待 32 if(ret>0)33 {34 printf("等待子进程成功,ret:%d,status:%d\n",ret,status);35 }36 //基本没有意义的,只是为了对比演示37 while(1)38 {39 printf("我是父进程,pid:%d,ppid:%d\n",getpid(),getppid());40 sleep(1);41 }42 }43 return 0;44 }
运行结果:
[jyf@VM-12-14-centos 进程]$ ./mytest10
我是父进程,pid:6469,ppid:31362
cnt:5,我是子进程,pid:6470,ppid:6469
cnt:4,我是子进程,pid:6470,ppid:6469
cnt:3,我是子进程,pid:6470,ppid:6469
cnt:2,我是子进程,pid:6470,ppid:6469
cnt:1,我是子进程,pid:6470,ppid:6469// printf("等待子进程成功,ret:%d,status:%d\n",ret,status);
等待子进程成功,ret:6470,status:13824// printf("等待子进程成功,ret:%d,status:%d\n",ret,(status>>8)&0xFF);
//等待子进程成功,ret:10928,status:54我是父进程,pid:6469,ppid:31362
我是父进程,pid:6469,ppid:31362
我是父进程,pid:6469,ppid:31362
我是父进程,pid:6469,ppid:31362
^C
通过waitpid参数options的值来控制阻塞式等待还是非阻塞式等待,options的值为0表示阻塞式等待,WNOHANG表示非阻塞式等待;
阻塞式等待时,父进程要等子进程结束后,才开始运行自己的程序;而非阻塞式等待父进程和子进程都在运行,仅仅判断当时那一次子进程的状态就返回了。
如果子进程已经返回,调用wait/waitpid后,wait/waitpid会立即返回,并且释放资源,获得子进程的退出信息
如果在任意时刻调用wait/waitpid,子进程还没退出,父进程可能阻塞
如果不存在该子进程,立即出错返回
1.父进程通过wait/waitpid可以拿到子进程的退出结果,为什么要用wait/waitpid函数呢?
进程具有独立性,那么数据会发送写时拷贝,父进程无法拿到,况且,信号呢?
2.既然进程具有独立性,进程退出码不也是子进程的的数据吗?父进程凭什么拿到?wait/waitpid究竟干了什么?
僵尸进程,至少要保留进程的PCB结构体,task_struct里面保留了任何进程退出时的结果信息;wait/waitpid究竟干了什么?本质其实就是读取子进程的task_struct结构体的信息。
3.wait/waitpid是系统调用,归系统管,task_struct是内核数据结构,所以有权限进行读取。
pid_t waitpid(pid_t pid,int* status,int options);
status并不是按照整数来整体使用的。
程序异常,不光光是内部代码有问题,也有可能是外力直接杀掉(子进程代码跑完了吗?不确定)
上一篇:上海华美达酒店(上海华美达酒店是几星级) 上海华美达酒店 上海华美达酒店浦东机场店
下一篇:郑州方特欢乐世界门票(郑州方特欢乐世界门票多少钱一位) 郑州方特欢乐世界门票包含夜场吗 郑州方特欢乐世界门票可以退吗