1、孤儿进程(Orphan Process)
父进程已亡,即父进程运行结束,但是子进程未结束的进程。
孤儿进程的父进程是1号进程-即init进程。
父进程死亡之后终端输入权释放。此时不能用ctrl-c结束进程。
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t pid;
pid = fork();
if(pid < 0)
{
printf("fork error.\n");
return -1;
}
else if(pid == 0)
{
while(1)
{
printf("in child process: father id is %d.\n",getppid());
sleep(1);
}
}
else
{
printf("in father process: my id is %d.\n",getpid());
sleep(5);
}
return 0;
}
在5s之后,父进程死亡,子进程的father id为1。编译和执行结果如下:
可以使用命令ps查看当前的进程,然后kill 29661结束子进程的运行。
也可以直接关闭该terminal。
2、僵尸进程(Zombie Process)
进程已经结束了,但是进程占用的资源没有完全回收(有标记存在)。
子进程死掉之后,父进程没有回收它所占用的资源。
导致子进程成为僵尸进程。父进程可用wait回收子进程的资源。
当父进程一直在运行,子进程运行提前结束,但是父进程没有用wait(&status)或wait(0)回收子进程的资源时,子进程成为僵尸进程。
当程序结束时,系统会自动回收僵尸进程占用的资源。
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t pid;
pid = fork();
if(pid < 0)
{
printf("fork error.\n");
return -1;
}
else if(pid == 0)
{
int i = 0;
for(i = 0;i < 6;i++)
{
printf("in child process: father id is %d.\n",getppid());
sleep(1);
}
}
else
{
while(1)
{
printf("in father process: my id is %d.\n",getpid());
sleep(3);
}
}
return 0;
}
编译和执行结果如下:
此时子进程已经结束,只有父进程在打印信息,可以用ctrl-c来释放终端。
此时打开另外一个终端:
可以看到fork5有两个进程,其中僵尸进程用<defunct>标注。
解决方法是在父进程中加入wait(0)或wait(&status).
3、守护进程/精灵进程(Daemon Process)
守护进程是个特殊的孤儿进程,这种进程脱离终端,在后台运行。
不接收来自终端的任何信号。