专栏首页程序员Linux下创建新进程

Linux下创建新进程

版权声明:本文为博主原创文章,转载请注明博客地址: https://blog.csdn.net/zy010101/article/details/83690667

创建新进程在Linux的下是由父进程来完成的,创建完成的新进程是子进程对于子进程它有两种执行顺序的可能性:

  1. 父进程和子进程并发执行;
  2. 子进程先执行,父进程等待子进程执行完毕。

另外新进程的地址空间也有两种可能性:

  1. 子进程是父进程的复制品(除了PID和task_struct中是子进程自己的,其余的都从父进程复制而来)
  2. 子进程装入另一个程序。

在Linux下的fork函数用于创建一个新的进程,使用fork()的函数来创建一个进程时,子进程只是完全复制父进程的资源。这样得到的子进程和父进程是独立的,具有良好的并发性。但是进程间通信需要专门的机制。

fork函数调用一次,会返回两个函数值,对于父进程而言,返回的是子进程的PID,对于子进程返回值是0;如果进程创建失败,那么返回给父进程-1。

Linux的采用了copy-on-write技术(COW),即:只有在子进程中发生写入操作的时候,才真正的去复制父进程的资源,否则不进行复制操作,比如在fork的子进程中只是调用exec函数来执行另外一个可执行文件,那么事实上就没有必要复制父进程的资源,这样会造成大量的开销浪费。

fork()函数创建的子进程和父进程的执行顺序理论上是不确定的(因为取决于OS的调度策略)。但是实际测试中总是父进程先执行,不知道是为什么。

总结一下:fork函数创建的子进程是父进程的复制,子进程和父进程并发执行来段代码测试一下。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    int num = 3;
    pid_t pid = 0;
    pid = fork();           //创建一个子进程,fork()函数没有参数。
    printf("pid is %d\n",getpid());     //获取进程的pid
    if (0 < pid)        //父进程得到的pid大于0,这段代码是父进程中执行的
    {
        num++;
        printf("I am parent!,num is %d\n",num);
    }
    else if(0 == pid)   //子进程得到的返回值是0,这段代码在子进程中执行
    {
        num--;
        printf("I am son!,num is %d\n",num);
    }   
   else                 //创建进程失败
   {
       //有两种情况会失败:
       //1.进程数目达到OS的最大值
       //2.进程创建时内存不够了。
       printf("fork error!\n");
       exit(-1);
   }
   
    
    return 0;
}

运行结果如下所示:

从运行结果可以看到,父子进程的PID是不同的,说明我们确实创建了一个进程。另外父子进程中的变量是独立的,这也说明了子进程是父进程的复制。当然,这样带来的坏处是进程间的通信必须使用专门的通信机制。此处使用的的if-else语句才能真正使得创建一个新进程有意义,否则父子进程将会执行一模一样的代码,这没有意义。

除了fork之外,Linux的系统还提供了vfork的函数来建立一个新进程.vfork建立的新进程和fork的不同之处在于:

  1. vfork创建的子进程和父进程是共享地址空间的,而不是复制,因此子进程中的数据和父进程中的数据是共享的,如果子进程中修改了某个变量的值,那么在父进程中这个变量也将被修改。优点是,子进程和父进程的通信很好解决。
  2. vfork创建的子进程必须调用_exit函数(或者使用exec函数调用另外的可执行程序)来结束它,否则子进程将不会结束。这点需要特别注意。
  3. vfork创建的子进程总是会在父进程之前执行,即使使用sleep函数(这个函数会将进程暂时挂起)也是先执行子进程,然后在执行父进程。

我们上代码来看看实际的运行效果。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
   
    int num = 3;
    pid_t pid;

    pid = vfork();          //使用vfork创建子进程
    if(0 < pid)
    {
        num++;
        printf("I am parent!,num is %d\n",num);
    }
    else if(0 == pid)
    {
        sleep(2);           //将子进程挂起2秒
        num--;
        printf("I am son!,num is %d\n",num);
    }
    else
    {
        printf("fork error!\n");
        exit(-1);
    }

    return 0;
}

等待了两秒后,运行结果如下:

我们看到父进程中打印的不对,而且发生了段错误(段错误就是内存越界了)。这就是和fork的不同之处,vfork的函数必须使用_exit来结束进程。否则就会出现错误。更改以后的代码输出如下所示:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
   
    int num = 3;
    pid_t pid;

    pid = vfork();          //使用vfork创建子进程
    if(0 < pid)
    {
        num++;
        printf("I am parent!,num is %d\n",num);
        exit(0);           //加上进程结束后,程序就能正常执行了
    }
    else if(0 == pid)
    {
        sleep(2);           //将子进程挂起2秒
        num--;
        printf("I am son!,num is %d\n",num);
    }
    else
    {
        printf("fork error!\n");
        exit(-1);
    }

    return 0;
}

可以看到子进程和父进程是共享数据的。而且子进程在父进程之前执行。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 为什么说 C 语言比 Java 难?

    “小伙子,我看你骨骼惊奇,是万中无一的编程奇才,维护世界和平就靠你了,我这有本秘籍《Java编程思想》,见与你有缘,就50块买给你了!”

    三哥
  • 使用对抗生成网络(GAN)生成手写字

    这是通过GAN迭代训练30W次,耗时3小时生成的手写字图片效果,大部分的还是能看出来是数字的。

    Awesome_Tang
  • Lagrange、Newton、分段插值法及Python实现

    数据分析中,经常需要根据已知的函数点进行数据、模型的处理和分析,而通常情况下现有的数据是极少的,不足以支撑分析的进行,这里就需要使用差值法模拟新的数值来满足需求...

    统计学家
  • 超全 | 只有高手才知道的C语言高效编程与代码优化方法(一)

    大雄总结了一些让程序运行更快的方法,可以帮助我们从执行速度和内存使用等方面来优化C语言代码。

    老九君
  • 让JNI告诉你 你的应用为什么被卸载

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huangliniqng/article/detail...

    黄林晴
  • Pandas 必备操作之 Index

    pandas 中的 index 是行索引或行标签。行标签可以说是 pandas 的灵魂一签,支撑了 pandas 很多强大的业务功能,比如多个数据框的 join...

    double
  • iOS标准库中常用数据结构和算法之位串

    所谓位串就是由0和1组成的bit串,比如:010010110011101101101011。可以把位串看成是元素只有0和1组成的数组。一般情况下大量数据的标志位...

    欧阳大哥2013
  • iOS标准库中常用数据结构和算法之内存池

    内存池提供了内存的复用和持久的存储功能。设想一个场景,当你分配了一块大内存并且填写了内容,但是你又不是经常去访问这块内存。这样的内存利用率将不高,而且无法复用。...

    欧阳大哥2013
  • E.Sequence in the Pocket

    用户2965768
  • Python在人工智能(AI)中的优势,年薪百万是互联网吹的泡沫吗?

    这本已是一个不需要争论的问题。如果说三年前,Matlab、Scala、R、Java 和 Python还各有机会,局面尚且不清楚,那么三年之后,趋势已经非常明确了...

    一墨编程学习

扫码关注云+社区

领取腾讯云代金券