1、课程目标
2、进程回收
- 子进程结束时需要父进程进行回收
- 孤儿进程由init进程进行回收(孤儿进程是子进程失去父进程的进程。init进程是内核启动首先启动的用户态进程,进程号1)
- 子进程结束,pcb(Processing Control Block,进程控制块)没有被回收,会变成僵尸进程。
3、进程回收-wait
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
- 父进程回收子进程成功返回回收子进程的进程号;回收失败返回EOF
- 若子进程没有结束父进程调用wait,父进程会一直处于堵塞状态
- 若父进程若有若干个子进程,优先回收结束的
- wait只能回收子进程的某一个进程。若需要对多个子进程进程回收,则需要父进程多次调用wait
- status指定保存子进程的返回值和结束方式的地址。
- status为NULL表示直接释放子进程PCB,不接收子进程的返回值和结束方式。
- wait调用成功会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,返回EOF
4、进程回收-wait-示例
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
int status;
int ret_wait;
pid_t pid;
if((pid = fork()) < 0)
{
perror("fork");
exit(-1);
}
else if(pid == 0)
{
sleep(2);
exit(2);
}
else
{
ret_wait = wait(&status);
printf(" ret_wait = %d\n status = 0x%x\n",ret_wait,status);
}
return 0;
}
5、进程返回值和结束方式
- 子进程通过exit/_exit/return返回正常结束时,会将其中返回值中低八位进行返回(0~255)
- 父进程调用wait(&status)回收
- WIFEXITED(status) 判断子进程是否正常结束
- WEXITSTATUS(status) 获取子进程的返回值
- WIFSIGNALED(status) 判断子进程是否被信号结束
- WTERMSIG(status) 获取结束子进程的信号类型
- 若低8位(7-0)为0,则进程正常结束。若高8位(15-8)为0,则进程由信号结束。
- 若信号结束,则低7位为信号结束值。若正常结束,则高8位(15—8)为正常退出的返回值。
6、进程回收-waitpid
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
- 调用函数成功返回回收子进程的PID(进程已经回收)或0(进程正常运行,等待回收),失败时返回EOF(进程回收失败)
- 参数pid可以指定回收的子进程。-1代表人已一个子进程。
- 参数status保存子进程的返回值和结束方式的地址。
- 参数status为NULL表示直接释放子进程PCB,不接收子进程的返回值和结束方式
- 参数option可以指定回收的方式,0表示阻塞回收和wait一样,WNOHANG表示非阻塞,立即返回,不会等待子进程结束,根据返回值的PID可以判断子进程处于已回收或者等待回收状态。
7、进程回收-waitpid-示例
ret_pid = waitpid(pid,&status,0);
ret_pid = waitpid(pid,&status,WNOHANG);
ret_pid = waitpid(-1,&status,0);
ret_pid = waitpid(-1,&status,WNOHANG);
8、进程小结
- wait以阻塞方式回收子进程
- waitpid笔wait灵活、可以以阻塞或非阻塞方式回收任意一个或固定一个子进程