Linux中的进程和fork函数(未写完)

本文介绍了在Linux系统中使用C语言实现进程创建的过程,重点解析了fork函数的工作原理。通过示例代码展示了fork如何创建父进程和子进程,并通过输出分析了进程间的独立性。此外,还提供了包含waitpid函数的示例代码,展示如何管理和同步父进程与子进程的执行。
摘要由CSDN通过智能技术生成

起因

        在复习Linux操作的时候发现了本科中涉及不深的知识点,在此记录一下。
        本科中,和进程有关的知识大概有进程的调度策略,进程和线程的关系。我能记得的差不多就是这些了。
        今天,我就在Linux中,使用C语言,来复现一下进程理论。为什么一定要是Linux系统呢?Linux系统编译C方便一点,而且我目前电脑上就有VSCode+WSL的环境,我相信其他环境一定也可以整理进程理论。

网上的第一个例子

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
      int ret = fork();
      if(ret == 0)
      {
          printf("I am child : %d, ret: %d\n", getpid(), ret);
      }
      else if(ret > 0)
      {
          printf("I am father : %d, ret: %d\n", getpid(), ret);
      }
      else
      {
          perror("fork");
          return 1;
      }
      return 0;
}

————引用信息————
版权声明:本文为CSDN博主「空白」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43697119/article/details/102767088

        保存为fork.c文件,使用gcc -o fork. fork.c命令编译后,会得到fork的可运行文件,./fork就可以运行了。以下是运行结果:

I am father : 680, ret: 681
I am child : 681, ret: 0

提问1

        代码自上而下执行,怎么会有两个输出?如果之前没有听过fork,那你会不会把这个理解为多线程?

回答1

        这里面最可疑的就是函数fork(定义在头文件unistd中)。当调用fork函数后,内核就会经行一系列的操作。这些操作我分成两个角度说,毕竟这里太乱了。

广义上

  1. 调用fork的进程称为父进程。
  2. 父进程触发fork函数后,会创建一个新进程(也可能创建失败),新进程称为子进程。
  3. 父进程和子进程是相对的,如果只对一个进程讨论,那么就没有父子的说法了。
  4. 父进程和子进程差不多相同,但是有细微差别。

细节上
出发fork函数后,内核(我们常常叫做系统)做的事情:

  1. 分配新的内存块和内核数据结构给子进程
  2. 将父进程的部分数据结构内容拷贝至子进程
  3. 添加子进程到系统进程列表当中
  4. fork返回,开始调度器调度

提问 2

        怎么操作子进程?代码中的ret(fork函数的返回值)是句柄嘛?拿到句柄就可以操作该进程嘛?还是类似Java中线程那样,通过一个类或者一个函数,把新进程要做的事情包裹起来?

回答 2

  1. 进程不是线程,fork创建的是进程,不是线程。虽然上面说到父进程,和子进程,但是从进程和线程概念上来说,父进程和子进程又是并列的。 他们都有一个标记进程的pid。代码中使用了getpid()函数,返回一个int类型的pid,我们还可以调用getppid()函数返回该进程的父进程pid。
  2. fork函数调用后,源代码会被粗暴的复制一份(不太严谨,我也没有深究)。见下图(来源:CSDN微微啦啦),然后两边独立执行。
    在这里插入图片描述
  3. fork函数的特点就是:调用一次返回两次。我们这么理解,在父进程(B)中fork的返回值与子进程(A)中fork的返回值是不一样的。B中的pid会返回当前进程号,A中pid是0。于是,并行的两段代码通过pid判断各自执行自己的那部分代码。

总结

下面我贴出我实验的代码,并作出解释。

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

int main()
{
    pid_t fpid; //fpid表示fork函数返回的值
    int count = 0;
    fpid = fork();
    if (fpid < 0)
        printf("error in fork!");
    else if (fpid == 0)
    {
        while (1)
        {
            sleep(2);
            printf("child %d\tfather %d\n", getpid(),getppid());
            count+=5;
            printf("[child] count value is \t%d\n",count);
        }
    }
    else if(fpid>0)
    {
        while (1)
        {
            sleep(3);
            printf("father %d\n", getpid());
            count+=1;
            printf("[father]count value is \t%d\n",count);
        }
        while (waitpid(-1, NULL, WNOHANG) > 0);
    }
    printf("统计结果是: %d\n", count);
    return 0;
}
}

运行结果

child 701       father 700
[child] count value is  5
father 700
[father]count value is  1
child 701       father 700
[child] count value is  10
father 700
[father]count value is  2
child 701       father 700
[child] count value is  15
child 701       father 700
[child] count value is  20
father 700
[father]count value is  3
child 701       father 700
[child] count value is  25
father 700
[father]count value is  4
child 701       father 700
[child] count value is  30
child 701       father 700
...

可以看到变量count出现了不同的数值,父进程和子进程是分开的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值