文章目录
- 进程等待
- 等待的必要性
- 进程等待的方法
- wait
- waitpid
- 获取子进程status
- 阻塞等待 与 非阻塞等待
进程等待
等待的必要性
-
子进程退出,父进程不进行回收的话,就可能造成僵尸进程,进而造成内存泄露
-
如果进程进入了僵尸状态,kill也杀不掉这个进程。因为谁也杀不死一个已经死去的进程
-
父进程派给子进程的任务完成的如何,使用者应该直到结果。子进程的任务是完成了还是未完成。
-
父进程通过进程等待(wait)的方式,回收子进程的资源,获取子进程的退出信息
-
父进程通过wait的方式,回收子进程的资源
子进程的退出信息,保存在子进程的pcb中。
进程等待的方法
#include<sys/types.h>
#incldue<sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
wait
pid_t wait(int *status);
- 默认进行阻塞等待,子进程没有退出,父进程就一直等待。
- 等待父进程的任意一个子进程退出。
- 返回值:
- >0:等待成功,返回值是等待子进程的pid
- <0:等待失败
- 参数:输出型参数,获取子进程的退出状态,如果不关心则可以设置为NULL
frok之后,父子进程谁先运行,不确定,是由操作系统的调度器运行。但是谁最后退出是确定的,父进程一定要最后退出,因为要等待子进程运行结束之后回收子进程。
waitpid
pid_t waitpid(pid_t pid, int *status, int options);
- 返回值:
- >0:等待成功,返回值是等待子进程的pid
- <0:等待失败
- 参数
- pid:
- pid=-1,等待人一个子进程,与wait等效
- pid>0,等待其进程id与pid值相等的子进程
- status:输出型参数,获取子进程的退出状态,如果不关心则可以设置为NULL
- options:0、非阻塞
- pid:
获取子进程status
- wait和waitpid,都有一个status参数,这个参数是一个输出型参数,由操作系统进行填充
- 如果传递NULL,表示不关心子进程的退出状态信息
- 如果不是NULL,则操作系统会根据该参数,将子进程的退出信息反馈给父进程
- status不能简单的当作整形来看待,应该当成位图来看,只考虑status的低16位。
status:0000 0000 0000 0000 0000 0000 0000 0000
信号编号 | 进程退出码 | 表示状态 |
---|---|---|
0 | 0 | 没有异常,结果正确 |
!0 | 0 | 出现异常,退出码无意义 |
0 | !0 | 没有异常,结果错误 |
!0 | !0 | 出现异常,退出码无意义 |
0~7,进程出现异常,收到的信号编号 | ||
9~15,进程正常结束的退出码 |
信号编号:status&0x7F
退出码:(status >> 8)& 0xFF
status:
- WIFEXITED(status):若为正常终止子进程返回的状态,则为真。(查看进程是否正常退出)。判定当前进程的退出信号是否为0,为0就为真,不为0就是假。
- WEXITSTATUS(status):若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)。
因为进程具有独立性,所以父子无法直接互相修改对方的数据之后,让对方看到。
因为读取子进程退出信息,本质上是读取内核数据,所以需要调用系统接口。
#include<sys/types.h>
#incldue<unistd.h>
#include<sys/wait.h>
int main()
{
pid_t id = fork();
if(id == 0)
{
int cnt = 5;
while(cnt)
{
printf("child is running, pid:%d, ppid:%d",getpid(),getppid());
sleep(1);
cnt--;
}
exit(0);
}
int status = 0;
pid_t rid = waitpid(id,&status,0);
if(id>0)
{
printf("wait success,rid:%d , status:%d, exitsigno:%d, exitcode :%d\n",rid,status,(status&0x7F),((status>>8)&0xFF));
}
}
阻塞等待 与 非阻塞等待
父进程阻塞等待,当子进程还在执行时,没有返回,父进程会将自己设置为阻塞状态,一直等待着子进程结束回收。
非阻塞等待,父进程检查子进程是否返回,如果子进程没有返回,不进行等待,父进程立刻返回,返回值为0。如果子进程已经返回,则返回子进程的id。
WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不予等待,若正常结束,则返回该子进程的id。
单次调用:非阻塞
基于非阻塞的轮询访问
机器宕机了,操作系统没有反应 – hang住了