深究 linux 的 fork 函数调用示例

咏月东南 2019-11-10

这里讲解几个在 Linux 操作系统上使用 fork 系统调用。(不定期更新)

一、atexit 函数

void cleanup(void) {
    printf("Cleaning up\n");
}
void fork6()
{
    atexit(cleanup);   printf("L0");   fork();   printf("L1");
    exit(0);
}

运行结果:

深究 linux 的 fork 函数调用示例

    int atexit(void (*func)(void))  函数,当进程正常结束时才会调用 atexit 中的 func 方法,无论你将 func 函数写在哪里。 

二、回收子进程

当一个进程由于某种原因终止时,内核并不立即将其从系统中清除。而是会保持在终止的状态等待父进程回收,这称之为 ”僵死进程“ 。当父进程回收已终止的进程时,内核将子进程的退出状态传递给父进程,然后抛弃已终止的进程。至此,该进程不存在。

如果一个父进程终止了,内核会安排 init 进程为它的孤儿进程的养父。

  在 64 位系统中,养父的进程号一般不为 1 ,而是一个随机进程号,但是这个进程的 cmd 都是 ”/lib/systemd/systemd --user"/  

(使用 ps -ef 命令查看)

深究 linux 的 fork 函数调用示例

   1. 子进程先结束,父进程循环挂起。儿子进程正常回收。

void fork7()
{
    if (fork() == 0) {
    /* Child */
    printf("Terminating Child, PID = %d\n", getpid());
    exit(0);
    } else {
    printf("Running Parent, PID = %d\n", getpid());
    while (1)
        ; /* Infinite loop */
    }
}

 运行结果:

 深究 linux 的 fork 函数调用示例

   2. 父进程先结束,子进程陷入循环挂起。

void fork8()
{
    if (fork() == 0) {
    sleep(1);
    /* Child */
    printf("Running Child, PID = %d\n", getpid());
    printf("Running Child, PPID = %d\n",getppid());
    while (1)
        ; /* Infinite loop */
    } else {
    printf("Terminating Parent, PID = %d\n", getpid());
    exit(0);
    }
}

运行结果:

深究 linux 的 fork 函数调用示例

   第二个代码样例中,父进程比子进程先结束运行,此时子进程成为孤儿进程,被收养。养父为前面介绍的进程。

3. 下面有一道对回收子进程有一定参考性的题。

int main(){

    int pid1, pid2, pid3, pid4, pid5;

    printf("1号进程开始\n");
    //得到第一个进程的pid
    pid1 = getpid();
    printf("PID1 = %d\n", pid1);

    //创建第二个进程
    pid2 = fork();
    if (pid2 == 0)
    {

        printf("2号进程开始\n");
        printf("PID2 = %d, Parent PID = %d\n", getpid(), getppid());
        printf("2号进程结束\n");

        //exit退出
        exit(0);
    }

    //创建第三个进程
    pid3 = fork();
    if (pid3 == 0)
    {
        printf("3号进程开始\n");
        printf("PID 3= %d, Parent PID = %d\n", getpid(), getppid());

        //在3号进程里面 创建第4个进程
        pid4 = fork();
        if (pid4 == 0)
        {
            printf("4号进程开始\n");
            printf("PID 4= %d, Parent PID = %d\n", getpid(), getppid());

            //sleep 3 second  等待3号进程结束,自己变成孤儿进程
            sleep(3);
            printf("4号进程结束\n");
            exit(0);
        }

        //在3号进程里面,创建第5个进程
        pid5 = fork();
        if (pid5 == 0)
        {
            printf("PID 5= %d, Parent PID = %d\n", getpid(), getppid());
            printf("5号进程开始\n");

            //sleep 3 second  等待3号进程结束,自己变成孤儿进程
            sleep(3);
            printf("5号进程结束\n");
            exit(0);
        }
        //等待子进程的结束  便于观察pid之间的关系
        printf("3号进程结束\n");                
        exit(0);
    }


    //等待子线程的结束 
    printf("1号进程结束\n");
    return 0;
}
————————————————
版权声明:本文为CSDN博主「张谷谷」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Paulhappy/article/details/50984888

编译代码使用下列命令

$ gcc -o process.out processes.c -lpthread

运行结果如下:

深究 linux 的 fork 函数调用示例

   该程序的进程图如下:

深究 linux 的 fork 函数调用示例

   

相关推荐