首页 > 技术文章 > Linux Guard Service - 守护进程分裂

liutianchen 2018-03-03 23:49 原文

分裂守护进程

由于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

处理僵尸进程

  1. 通过信号机制
    子进程退出时向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait进行处理僵尸进程。
  2. fork两次
    《Unix 环境高级编程》8.6节说的非常详细。原理是将子进程成为孤儿进程,从而其的父进程变为init进程,通过init进程可以处理僵尸进程。
使用信号机制处理僵尸进程

在源文件中使用

signal(SIGCLD, SIG_IGN);

通知内核本进程不关心子进程的结束,子进程将被init释放

13206 ?        Ss     0:00 ./test3-2

推荐阅读