分裂守护进程
由于fork()后第一行仍然在循环中,使用fork()返回值鉴别当前进程的性质
int i = 0;
for (i = 0; i < 10; i++) {
// sleep(1);
printf("new fork() process pid = %d \n", pid);
pid = fork();
if (pid == 0) break;
}
pid==0时说明该进程为子进程不能再进行循环(否则将不断创造进程直到子进程上限)
子进程和父进程的关系
1. 子进程的fork()返回值为0
2. 子进程的pid序号紧接着父进程的序号
创建10个子进程
[root@localhost 03]# new fork() process pid = 11250
new fork() process pid = 11251
new fork() process pid = 11252
new fork() process pid = 11253
new fork() process pid = 11254
new fork() process pid = 11255
new fork() process pid = 11256
new fork() process pid = 11257
new fork() process pid = 11258
new fork() process pid = 11259
[root@localhost 03]#
[root@localhost 03]#
观察系统守护进程树
11250 ? Ss 0:00 ./test3-1
11251 ? S 0:00 \_ ./test3-1
11252 ? S 0:00 \_ ./test3-1
11253 ? S 0:00 \_ ./test3-1
11254 ? S 0:00 \_ ./test3-1
11255 ? S 0:00 \_ ./test3-1
11256 ? S 0:00 \_ ./test3-1
11257 ? S 0:00 \_ ./test3-1
11258 ? S 0:00 \_ ./test3-1
11259 ? S 0:00 \_ ./test3-1
11260 ? S 0:00 \_ ./test3-1
[root@localhost 03]#
fork()返回值的关系
在子进程中,fork返回值为0
在父进程中,fork返回值为子进程的pid
子进程直接复制父进程的PCB然后在fork紧接着的下一行开始执行(以防止fork中套fork的死循环情况)
僵尸进程
任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。
12711 ? Ss 0:00 ./test3-1
12712 ? Z 0:00 \_ [test3-1] <defunct>
12713 ? Z 0:00 \_ [test3-1] <defunct>
12722 ? Z 0:00 \_ [test3-1] <defunct>
12723 ? Z 0:00 \_ [test3-1] <defunct>
12724 ? Z 0:00 \_ [test3-1] <defunct>
12725 ? Z 0:00 \_ [test3-1] <defunct>
12726 ? Z 0:00 \_ [test3-1] <defunct>
12727 ? Z 0:00 \_ [test3-1] <defunct>
12729 ? Z 0:00 \_ [test3-1] <defunct>
12730 ? Z 0:00 \_ [test3-1] <defunct>
僵尸进程在ps -xf中的表示
杀死僵尸进程
使用pkill加进程名称,杀死全部进程
pkill test3-1
处理僵尸进程
- 通过信号机制
子进程退出时向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait进行处理僵尸进程。 - fork两次
《Unix 环境高级编程》8.6节说的非常详细。原理是将子进程成为孤儿进程,从而其的父进程变为init进程,通过init进程可以处理僵尸进程。
使用信号机制处理僵尸进程
在源文件中使用
signal(SIGCLD, SIG_IGN);
通知内核本进程不关心子进程的结束,子进程将被init释放
13206 ? Ss 0:00 ./test3-2