Linux之进程等待
创始人
2025-05-28 06:48:57
0

进程等待

  • 1.进程等待的必要性
  • 2.进程等待的方法
    • 2.1具体代码(重要)
  • 3.status的构成

1.进程等待的必要性

之前讲过,子进程退出,父进程如果不管不顾,就可能造成僵尸进程的问题,进而造成内存泄漏。
另外,一旦一个进程变成僵尸状态,那就刀枪不入,“杀人不咋眼”的kill -9也无能为力,因为谁也没有办法杀死一个已经死去的进程。
最后,父进程派给子进程的任务完成的如何,我们需要知道,如,子进程运行完成,结果对还是不对或者是否正常退出。
父进程通过进程等待的方式,回收子进程的资源,获取子进程退出信息。

2.进程等待的方法

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);

2.1具体代码(重要)

#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是内核数据结构,所以有权限进行读取。

3.status的构成

pid_t waitpid(pid_t pid,int* status,int options);

status并不是按照整数来整体使用的。

  1. wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。
  2. 如果传递NULL,表示不关心子进程的退出状态信息
  3. 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。
  4. status不能简单的当作整型来看待,可以当作位图来看待,具体细节如下图,status是32个比特位的,我们现在只学习其低16位。

在这里插入图片描述
在这里插入图片描述
程序异常,不光光是内部代码有问题,也有可能是外力直接杀掉(子进程代码跑完了吗?不确定)

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...