进程回收
子进程结束时由父进程回收
孤儿进程由init进程回收
若没有及时回收会出现僵尸进程
wait()和waitpid()
(1)函数说明:
wait()函数用于使父进程(也就是调用 wait()的进程)阻塞(暂时停止目前进程的执行),直到一个子进程结束或者该进程接到了一个指定的信号为止。如果该父进程没有子进程或者他的子进程已经结束,则 wait()会立即返回-1。子进程的结束状态值会由参数status 返回, 而子进程的进程识别码也会一快返回。如果不在意结束状态值, 则参数status可以设成NULL。
阻塞(pend)就是任务释放CPU,其他任务可以运行,一般在等待某种资源或信号量的时候出现。挂起(suspend)不释放CPU,如果任务优先级高就永远轮不到其他任务运行,一般挂起用于程序调试中的条件中断,当出现某个条件的情况下挂起,然后进行单步调试。
waitpid()的作用和 wait()一样,但它并不一定等待第一个终止的子进程。waitpid()有若干选项,可提供一个非阻塞版本的 wait()功能。实际上 wait()函数只是 waitpid()函数的一个特例,在 Linux 内部实现 wait()函数时直接调用的就是 waitpid()函数。
wait()函数族语法
头文件 | #include <sys/types.h> #include <sys/wait.h> |
---|---|
函数原型 | pid_t wait(int *status); |
函数传入值 | status 指向的整型对象用来保存子进程结束时的状态。另外,子进程的结束状态可由 Linux 中一些特定的宏来测定 |
函数返回值 | 成功:已回收的子进程的进程号 失败:-1 |
子进程通过exit / _exit / return 返回某个值(0-255)
父进程调用wait(&status) 回收
WIFEXITED(status) 判断子进程是否正常结束
WEXITSTATUS(status) 获取子进程返回值
WIFSIGNALED(status)判断子进程是否被信号结束
WTERMSIG(status) 获取结束子进程的信号类型;
int main(int argc, const char *argv[])
{
pid_t pid;
int status,i;
if(fork() == 0)
{
printf("This is the child process .pid =%d\n",getpid());
exit(5); // 子进程的返回值
}
else
{
sleep(1);
printf("This is the parent process ,wait for child...\n");
pid=wait(&status);// 获取回收子进程的的进程号
i=WEXITSTATUS(status);//获取子进程返回值
printf("child's pid =%d .exit status= %d\n",pid,i);
}
return 0;
}
waitpid()函数语法
头文件 | #include <sys/types.h> #include <sys/wait.h> |
---|---|
函数原型 | pid_t waitpid(pid_t pid, int *status, int options); |
函数传入值 | pid pid > 0:回收进程 ID 等于 pid 的子进程 pid = 1:回收任何一个子进程,此时和 wait()作用一样 pid = 0:回收其组 ID 等于调用进程的组 ID 的任一子进程 pid < 1:回收其组 ID 等于 pid 的绝对值的任一子进程 |
函数传入值 | status : 同 wait() options: WNOHANG:若指定的子进程没有结束,则 waitpid()不阻塞而立即返回,此时返回值为 0 WUNTRACED:为了实现某种操作,由 pid 指定的任一子进程已被暂停,且其状态自暂停以来还未报告过,则返回其状态 0:同wait(),阻塞父进程,直到指定的子进程退出 |
函数返回值 | >0:已经结束运行的子进程的进程号 0:使用选项 WNOHANG 且没有子进程退出 -1:出错 |
waitpid()使用示例。
由于 wait()函数的使用较为简单,在此以 waitpid()为例进行讲解。本例中首先使用 fork()创建一个子进程,然后让子进程暂停 5s(使用了 sleep()函数)。接下来对原有的父进程使用 waitpid()函数,并使用参数 WNOHANG 使该父进程不会阻塞。若有子进程退出,则 waitpid()返回子进程号;若没有子进程退出,则 waitpid()返回 0,并且父进程每隔 1s 循环判断一次
int main(int argc, const char *argv[])
{
pid_t pid, ret;
pid = fork();
if(pid < 0 )
{
printf("Error fork\n");
}
else if (pid == 0)/*子进程*/
{
/*子进程暂停 5s*/
sleep(5);
/*子进程正常退出*/
exit(0);
}
else/*父进程*/
{
/*循环测试子进程是否退出*/
do
{
/*调用 waitpid,且父进程不阻塞*/
ret = waitpid(pid, NULL, WNOHANG);
/*若子进程还未退出,则父进程暂停 1s*/
if(ret == 0)
{
printf("The child process has not exited \n ");
sleep(1);
}
}while(ret == 0);
/*若发现子进程退出,打印出相应情况*/
if(pid == ret)
{
printf(" The child process exited \n");
}
else
{
printf("some error occured \n");
}
}
return 0;
}
如果把 ret = waitpid(pid, NULL, WNOHANG); 改为 ret = waitpid(pid, NULL, 0); 父进程会一直阻塞,直到子进程结束为止,运行的结果如下。