C语言fork一个进程 Linux

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/mrtwenty/article/details/98798161

进程的相关知识笔记:

       进程是一个程序的执行过程。多个进程分时复用CPU,当分配给进程的时间片结束后,内核会收回进程对CPU的使用权,转而给系统的其他进程执行,而之前的进程就需要进入睡眠态,相关的数据就会先保存起来,等候CPU的调度。所以一个进程的生命周期有很多不同的状态,通常进程的状态被划分为5种:初始态、就绪态、运行态、睡眠态、终止态。

       在系统中每一个进程都有一个进程id,简称pid (process id),进程有父子关系、兄弟关系,每一个进程都有一个父亲,父进程的进程id,叫做ppid。所以系统里面的进程会形成一个进程树,使用pstree命令可以查看当前系统的进程树。以前进程的顶端是init进程,进程号为1,现在有的linux系统使用systemd作为系统的顶级进程,进程号也是1,至于两者的区别,可以谷歌查阅相关的资料,当我们fork一个进程后,代码从fork后,分别由两个进程执行,父子进程的执行顺序无法预测。当子进程执行完,父进程没有进行回收处理,就会出现僵尸进程(defunct进程),当父进程执行完,子进程还没执行完,子进程就变成孤儿进程,这是systemd就会认领,负责回收处理。

下面就是一个利用fork函数,创建子进程的例子:

#include <stdio.h>  //标准的输入输出函数
#include <stdlib.h> //standard library标准库函数头文件
#include <unistd.h> //对于类 Unix 系统,unistd.h 中所定义的接口通常都是大量针对系统调用的封装 fork、

int main()
{
    pid_t pid;
    
    pid=fork(); //创建一个进程,下面的代码, 由两个进程分别执行,父子进程执行顺序无法预测
    // pid 在两个不同的进程中,返回的结果不一样
    
    // 这是异常情况
    if (pid==-1)
    {
        perror("fork失败!");
        exit(1);
    }

    //返回大于0的进程就是父进程
    if(pid>0)  //父进程
    {
        printf("父进程: pid= %d , ppid=%d,子进程: %d \n", getpid(),getppid(),pid);

        sleep(1); //这里延迟父进程程序,等子进程先执行完。
    }
    else if(pid==0)  //子进程
    { 
        printf("子进程: pid= %d , ppid=%d \n", getpid(),getppid());
    }

    printf("执行完成!\n"); //由两个进程执行,当然输出两次

    return 0; //养成好习惯,返回程序执行状态码
}

请留意sleep(1); 这段代码, 并尝试注释后,重新编译一个,然后执行他们,看看有加sleep和没有的区别,

有加sleep(1);会输出:

       父进程: pid= 17571 , ppid=16415,子进程: 17572 
       子进程: pid= 17572 , ppid=17571 
       执行完成!
       执行完成!

注: 子进程先执行完,父进程还没死,此时子进程ppid就是父进程的pid

没有加sleep;可能会输出:

       父进程: pid= 17580 , ppid=16415,子进程: 17581 
       执行完成!
       子进程: pid= 17581 , ppid=1 
       执行完成!

注: 父进程先执行完,子进程还没,子进程被systemd接收,子进程的ppid就变成了1。

本文参考Linux编程基础一书。

猜你喜欢

转载自blog.csdn.net/mrtwenty/article/details/98798161
今日推荐