Linux 的连续三次调用 fork

今天一个考研复试的同学问我一个问题:
在这里插入图片描述

感觉对 fork 的理解挺有代表性的。

#include<stdio.h>
#include<unistd.h>

int main()
{
    pid_t pid;
    int count = 0;
    pid = fork();   //fork一个进程
    if(pid == 0)
    {               //pid为0,
        printf("this is child process, pid is %d\n",getpid()); //getpid返回的是当前进程的PID
        count += 2;
        printf("count = %d\n",count);
        return 0;
    }
    else if(pid > 0)
    {
        printf("this is father process, pid is %d\n",getpid());
        count++;
        printf("count = %d\n",count);
        return 0;
    }
    else
    {
        fprintf(stderr,"ERROR:fork() failed!\n");
    }
    return 0;
}

这是一个简单的 fork 调用函数说明 pid 为 0 即进入的是子进程的逻辑, pid > 0 则表示进入父进程。

一般在多进程编程时,会将 fork 的返回值来做判断进入的是哪个进程。(ps 我现在用得更多是多线程并发)

[kywlzr@localhost test_fork]$ gcc test_fork.c -o test_fork
[kywlzr@localhost test_fork]$

进行编译,得到 test_fork 函数,执行一下

this is father process, pid is 3106
count = 1
[kywlzr@localhost test_fork]$ this is child process, pid is 3107
count = 2

可以看到父子进程的 pid 是不一样的

然后再来看看题目这个写法:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 
  4 int main()
  5 {
  6     pid_t pid[3];
  7     pid[0] = fork();
  8     pid[1] = fork();
  9     pid[2] = fork();
 10     sleep(100);
 11     printf("this is process\n");
 12 
 13     return 0;
 14 }
 15 
 16 


一样编译一下

[kywlzr@localhost test_fork_2]$ gcc test_fork_2.c -o test_fork_2
[kywlzr@localhost test_fork_2]$

再运行

[kywlzr@localhost test_fork_2]$ ./test_fork_2

再来看看名字叫 test_fork_2 的进程有几个

[kywlzr@localhost ~]$ ps -ef | grep test_fork_2 | grep -v grep
kywlzr 3190 3060 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3191 3190 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3192 3190 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3193 3190 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3194 3192 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3195 3191 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3196 3191 0 18:08 pts/2 00:00:00 ./test_fork_2
kywlzr 3197 3195 0 18:08 pts/2 00:00:00 ./test_fork_2

没错,就是有 8 个,其中有 3 个的父进程都是 3190,有两个的父进程是 3191。

3190 就是最开始这个进程

第一次调用 fork() ,产生第一个子进程 3191,这个时候 3190 和 3191 都继续执行剩余的两次 fork()(代码 8 9 行)

3190 又产生一个子进程 3192;

3191 产生的子进程是 3195;

最后 3190 3191 3192 3195 都在执行第 9 行的 fork() 函数

3190 产生 3193

3192 产生 3194

3192 产生 3196

3195 产生 3197

过程参考此图
在这里插入图片描述

那这就有一个问题了,进程号的顺序应该是按执行的先后顺序安排的,那为什么 3192 进程会在 3191 之前执行呢?

我猜这是个栈?可以看看 fork 4次的结果

[kywlzr@localhost ~]$ ps -ef | grep test_fork_2 | grep -v grep
kywlzr 3256 3060 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3257 3256 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3258 3256 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3259 3256 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3260 3256 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3261 3259 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3262 3258 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3263 3258 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3264 3257 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3265 3257 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3266 3257 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3267 3262 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3268 3264 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3269 3264 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3270 3265 0 18:31 pts/2 00:00:00 ./test_fork_2
kywlzr 3271 3268 0 18:31 pts/2 00:00:00 ./test_fork_2

验证了我的猜想= =但是 3257 这个进程有点怪,它的子进程是 3264 3265 3266 为什么不是 3265 先创建子进程,而是 3264 先创建??(留个坑)

如果想创建三个子进程呢?

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

int main(int argc, char *argv[])
{
    int i,j,status;
    int pid[3];

    for(i = 0; i < 3; i++)
    {
        if((pid[i] = fork()) >0)
        {

            printf("This is child process pid=%d\n",pid[i]);

        }
        else
        {
            printf("This is father process pid=%d\n",pid[i]);
            exit( 0);
        }

    }

    return 0;
}

输出结果:

[kywlzr@localhost test_fork_3]$ ./test_fork_3
This is child process pid=2618
This is child process pid=2619
This is child process pid=2620
[kywlzr@localhost test_fork_3]$ This is father process pid=0
This is father process pid=0
This is father process pid=0

参考:《linux下连续三次fork() --深度理解进程创建函数》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值