操作系统---之fork()函数

【Linux】关于理解fork()函数的简单例子

原创 2016年06月19日 00:13:18

1.fork()函数

fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,这个新产生的进程称为子进程。一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。需要注意的一点:就是调用fork函数之后,一定是两个进程同时执行的代码段是fork函数之后的代码,而之前的代码以及由父进程执行完毕。下面来看一个很简单的例子。
fork函数返回两个值

  • 返回一个大于0的值给父进程
  • 返回0给子进程
  • 返回其他值说明fork失败了

2.关于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);
    }
    else if(pid > 0)
    {
        printf("this is father process, pid is %d\n",getpid());
        count++;
        printf("count = %d\n",count);
    }
    else
    {
        fprintf(stderr,"ERROR:fork() failed!\n");
    }
    return 0;
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

下面是运行结果:
这里写图片描述
  有人会对这个运行结果产生一种错觉,就是程序中if语句的两条分支if(pid == 0)和else if(pid > 0)都得到了执行,其实完全不是这么回事,出现这种运行结果的原因是因为,在main()函数的第6行fork了一个进程,这个进程称为原来进程的子进程,原来的那个进程称为父进程,这个进程与原来的进程并发执行,谁先税后没有规律,由操作系统调度决定。
  我们用gdb工具对这个程序单步执行调试一下,可能会对这个过程了解的更清晰一些。

3.使用gdb调试父进程。

1.输入gdb a.out然后输入start开始调试,此时终端显示即将执行的代码
这里写图片描述
2.输入n,执行当前一行代码,同时显示下一条将执行的代码
这里写图片描述
即将创建一个子进程,当前进程为父进程。
3.再输入n执行pid=fork()语句
这里写图片描述
这个时候,终端上显示

Detaching after fork from child process 2755.
this is child process, pid is 2755
count = 2
  
  
  • 1
  • 2
  • 3

这个时候,说明已经新建了一个子进程,子进程PID是2755,而且由于我们现在单步调试的是父进程,并不影响子进程的执行,这个子进程只有几行代码,这个时候已经执行完了,并且在终端上显示了执行结果,就是下面两行内容。

this is child process, pid is 2755
count = 2
  
  
  • 1
  • 2

4.这个时候,我们输入p pid看一下fork函数返回给父进程的值是不是子进程的PID
这里写图片描述
果然就是子进程的PID值。
5.输入n接着执行判断语句
这里写图片描述
由于pid的值为2755,因此跳过了if(pid==0)分支内的语句,转而判断pid是否大于0
6.输入n接着判断pid是否大于0
这里写图片描述
pid的值大于0,执行分支内的语句。
7.接着输入n,直到程序正常结束
这里写图片描述

上面是父进程的调试过程,其实子进程也可以用gdb来调试,下次再说。

4.使用ps aux命令查看父进程和子进程

  ps aux命令可以查看系统中正在运行的所有进程,不过我们这个例子代码很少,系统瞬间就能执行完毕,用ps aux命令根本捕捉不到。因此我们在代码中做一些修改。
  

#include<stdio.h>
#include<unistd.h>
int main()
{
    pid_t pid;
    int count = 0;
    pid = fork();   //fork一个进程
    if(pid == 0)
    {               //pid0,
        printf("this is child process, pid is %d\n",getpid());
        count+=2;
        printf("count = %d\n",count);
    }
    else if(pid > 0)
    {
        printf("this is father process, pid is %d\n",getpid());
        count++;
        printf("count = %d\n",count);
    }
    else
    {
        fprintf(stderr,"ERROR:fork() failed!\n");
    }
    sleep(10);//新加入的行,让程序在这里暂停10秒,父进程和子进程都会执行这行代码
    return 0;
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

我们在第30行加入了一条语句,让程序暂停10s
重新编译程序,然后执行程序,输入./a.out后,快速切换到另外一个终端(如果你手速慢的话,多暂停一会儿就可以),输入ps aux查看正在运行的进程。
执行程序:
这里写图片描述

切换终端,输入ps aux查看进程
这里写图片描述
可以看到a.out程序产生了两个进程,父进程PID是2928,子进程PID是2929。


转载:https://blog.csdn.net/ww1473345713/article/details/51708003

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值