孤儿进程
/*
* @file orphan.c
* @brief 父进程比子进程先结束,子进程变成了孤儿进程,由init进程回收
* @version 1.1 无
* @author 北豼
* @date 2022年5月9日
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0) //子进程
{
while(1) //循环打印让父进程先结束,子进程变成孤儿进程
{
printf("I am child,my parent pid = %d\n", getppid());
sleep(1);
}
}
else if (pid > 0) //父进程
{
printf("I am parent,my pid is %d\n", getpid());
sleep(5);
printf("-------parent going to die---------\n");
}
else if (pid == -1) //创建子进程失败
{
perror("fork error");
exit(1);
}
return 0;
}
刚开始的父进程是11872,后来父进程11872先结束了,子进程就变成孤儿进程了,父进程变成1了,即是init进程
,由这个init进程
进行子进程的回收
僵尸进程
/*
* @file zoom.c
* @brief 子进程结束了,父进程也没有回收回收残留的资源,就变成僵尸进程了
* @version 1.1 无
* @author 北豼
* @date 2022年5月9日
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0) //子进程
{
printf("I am child, my parent %d, going to sleep 10s\n", getppid());
sleep(10);
printf("-----------child die-------------\n");
}
else if (pid > 0) //父进程
{
while(1) //子进程结束后,父进程并没有对子进程进行回收,导致子进程变成僵尸进程
{
printf("I am parent, pid = %d,myson = %d\n", getpid(), pid);
sleep(1);
}
}
else if (pid == -1) //子进程创建失败
{
perror("fork error");
exit(1);
}
return 0;
}
子进程结束了,父进程也没有回收回收残留的资源,就变成僵尸进程了
这里看到的括号括起来的zoom
就是僵尸态了
wait函数
wait函数
用wait函数
阻塞等待子进程结束,再由父进程粗略回收,但不知道子进程结束的状态
/*
* @file zoom_wait.c
* @brief 用wait函数阻塞等待子进程结束,再由父进程粗略回收,但不知道子进程结束的状态
* @version 1.1 无
* @author 北豼
* @date 2022年5月9日
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
pid_t wpid;
//创建一个子进程
pid = fork();
if (pid == 0) //子进程
{
printf("I am child, my parent %d, going to sleep 10s\n", getppid());
sleep(10);
printf("-----------child die-------------\n");
}
else if (pid > 0) //父进程
{
wpid = wait(NULL); //阻塞等待子进程结束,回收子进程
if(wpid == -1) //回收子进程失败
{
perror("wait error");
exit(1);
}
while(1) //这里子进程已经被回收,弄一个while,方便去查看是否还有僵尸进程
{
printf("I am parent, pid = %d,myson = %d\n", getpid(), pid);
sleep(1);
}
}
else if (pid == -1) //创建子进程失败
{
perror("fork error");
exit(1);
}
return 0;
}
这样子父进程就可以回收到子进程了,就不会留下子进程的残留了
用wait函数
阻塞等待子进程结束,再执行父进程,这里精确回收,得到了子进程结束的状态,子进程正常结束
/*
* @file wait1.c
* @brief 用wait函数阻塞等待子进程结束,再执行父进程,这里精确回收,得到了子进程结束的状态,子进程正常结束
* @version 1.1 无
* @author 北豼
* @date 2022年5月9日
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
pid_t wpid;
int status;
//创建一个子进程
pid = fork();
if (pid == 0) //子进程
{
printf("I am child, my parent %d, going to sleep 10s\n", getppid());
sleep(10);
printf("-----------child die-------------\n");
exit(76); //进程正常结束
}
else if (pid > 0) //父进程
{
wpid = wait(&status); //阻塞等待子进程结束,回收子进程
if (wpid == -1) //回收子进程失败
{
perror("wait error");
exit(1);
}
if (WIFEXITED(status)) //子进程正常结束
{
printf("child exit with %d\n", WEXITSTATUS(status)); //打印输出exit的参数
}
while(1) //这里子进程已经被回收,弄一个while,方便去查看是否还有僵尸进程
{
printf("I am parent, pid = %d,myson = %d\n", getpid(), pid);
sleep(1);
}
}
else if (pid == -1) //创建子进程失败
{
perror("fork error");
exit(1);
}
return 0;
}
用wait函数
阻塞等待子进程结束,再执行父进程,这里精确回收,得到了子进程结束的状态,子进程异常结束
/*
* @file wait2.c
* @brief 用wait函数阻塞等待子进程结束,再执行父进程,这里精确回收,得到了子进程结束的状态,子进程异常结束
* @version 1.1 无
* @author 北豼
* @date 2022年5月9日
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
pid_t wpid;
int status;
//创建一个子进程
pid = fork();
if (pid == 0) //子进程
{
printf("I am child, my parent %d, going to sleep 10s\n", getppid());
sleep(60); //这里阻塞60s,留着去kill子进程
printf("-----------child die-------------\n");
exit(76);
}
else if (pid > 0) //父进程
{
wpid = wait(&status); //阻塞等待子进程结束,回收子进程
if (wpid == -1) //回收子进程失败
{
perror("wait error");
exit(1);
}
if (WIFEXITED(status)) //子进程正常结束
{
printf("child exit with %d\n", WEXITSTATUS(status));
}
if (WIFSIGNALED(status)) //子进程异常结束
{
printf("child killed by %d\n", WTERMSIG(status));
}
while (1)
{
printf("I am parent, pid = %d,myson = %d\n", getpid(), pid);
sleep(1);
}
}
else if (pid == -1) //创建子进程失败
{
perror("fork error");
exit(1);
}
return 0;
}
这里用kill
杀死子进程
wait函数得到了子进程结束的状态
回收多个子进程
上面已经用过wait函数
来回收一个子进程,现在用wait函数
来回收多个子进程
/*
* @file wait3.c
* @brief 用wait函数来回收多个子进程
* @version 1.1 无
* @author 北豼
* @date 2022年5月9日
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
int i;
pid_t pid;
//创建5个子进程
for (i = 0; i < 5; i++)
{
pid = fork();
if (pid == 0) //父进程继续循环,直到循环结束,子进程退出循环
{
break;
}
}
//判断是父进程还是子进程
if(i < 5)
{
sleep(i);
printf("I am %d child, pid = %u\n", i+1, getpid());
}
else
{
sleep(i);
printf("I am parent\n");
while (wait(NULL)); //循环回收多个子进程
}
return 0;
}
waitpid函数
用waitpid函数
回收指定子进程
waitpid函数
的第三个参数为0是阻塞回收,跟wait函数
一样
/*
* @file waitpid1.c
* @brief 用waitpid函数回收指定子进程
* @version 1.1 无
* @author 北豼
* @date 2022年5月9日
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
int i;
pid_t pid;
pid_t p;
//循环创建5个子进程
for (i = 0; i < 5; i++)
{
pid = fork();
if (pid == 0)
{
break;
}
else if (i == 3)
{
p = pid;
}
}
if (i < 5)
{
sleep(i);
printf("I am %d child, pid = %u\n", i+1, getpid());
}
else
{
sleep(i);
printf("I am parent\n");
waitpid(p, NULL, 0); //阻塞等待回收指定的子进程
while (1);
}
return 0;
}
可以看出指定回收的第四个子进程已经被回收了
用waitpid函数
回收多个子进程
/*
* @file waitpid2.c
* @brief 用waitpid函数回收多个子进程
* @version 1.1 无
* @author 北豼
* @date 2022年5月9日
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
int i;
pid_t pid;
//循环创建5个子进程
for (i = 0; i < 5; i++)
{
pid = fork();
if (pid == 0)
{
break;
}
}
if (i < 5)
{
sleep(i);
printf("I am %d child, pid = %u\n", i+1, getpid());
}
else
{
sleep(i);
printf("I am parent\n");
while (waitpid(-1, NULL, 0)); //等价于while(wait(NULL));
}
return 0;
}
可以看到所有子进程都被回收了
当waitpid函数
的第三个参数为WNOHANG
,为轮询回收子进程,子进程正在运行的时候,返回值为0
轮询回收多个子进程
/*
* @file waitpid3.c
* @brief 用waitpid函数轮询回收多个子进程
* @version 1.1 无
* @author 北豼
* @date 2022年5月9日
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void)
{
int i;
int n = 5;
pid_t pid;
pid_t wpid;
//循环创建5个子进程
for (i = 0; i < 5; i++)
{
pid = fork();
if (pid == 0)
{
break;
}
}
if (i < 5)
{
sleep(i);
printf("I am %d child, pid = %u\n", i+1, getpid());
}
else
{
sleep(i);
printf("I am parent\n");
do
{
wpid = waitpid(-1, NULL, WNOHANG); //轮询回收子进程
if (wpid > 0)
{
n--;
}
sleep(1);
}while (n > 0);
while (1);
}
return 0;
}
子进程已全部回收