随笔 - 18  文章 - 2  评论 - 0  阅读 - 17315

[APUE]fork后子进程的运行情况

转自:http://blog.csdn.net/koches/article/details/7787468

 

fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:    

1)在父进程中,fork返回新创建子进程的进程ID;    

2)在子进程中,fork返回0;    

3)如果出现错误,fork返回一个负值;

创建新进程成功后,系统中出现两个基本完全相同的进程,这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。此时,两个进程都从fork开始往下执行,只是pid不同。

有人可能疑惑为什么不是从#include处开始复制代码的?看下图:

      上图表示一个含有fork的程序,而fork语句可以看成将程序切为A、B两个部分。然后整个程序会如下运行:

      step1、设由shell直接执行程序,生成了进程P。P执行完Part. A的所有代码。

      step2、当执行到pid = fork();时,P启动一个进程Q,Q是P的子进程,和P是同一个程序的进程。Q继承P的所有变量、环境变量、程序计数器的当前值。

      step3、在P进程中,fork()将Q的PID返回给变量pid,并继续执行Part. B的代码。

      step4、在进程Q中,将0赋给pid,并继续执行Part. B的代码。

      这里有三个点非常关键:

      1、P执行了所有程序,而Q只执行了Part. B,即fork()后面的程序。(这是因为Q继承了P的PC-程序计数器)

      2、Q继承了fork()语句执行时当前的环境,而不是程序的初始环境。

      3、P中fork()语句启动子进程Q,并将Q的PID返回,而Q中的fork()语句不启动新进程,仅将0返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <unistd.h>
#include <sys/types.h>
 
void main ()
 {
          pid_t pid;
          printf("hello!\n"); 
          pid=fork();
 
         if (pid < 0)
                  printf("error in fork!");
          else if (pid == 0)
                  printf("i am the child process, my process id is %d\n ",getpid());
          else
                  printf("i am the parent process, my process id is %d\n",getpid());
 
         printf("bye!\n");
 }

 

这里可以看出parent process执行了printf("hello!\n");  而child process 没有执行printf("hello!\n"); 

有一个让人很迷惑的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <unistd.h>
#include <sys/types.h>
 
 void main ()
 {
          pid_t pid;
          printf("fork!");    //printf("fork!\n")
 
         pid=fork();
 
          if (pid < 0)
                  printf("error in fork!\n");
          else if (pid == 0)
                  printf("i am the child process, my process id is %d\n",getpid());
          else
                  printf("i am the parent process, my process id is %d\n",getpid());
 }

 

此时打印输出了两个fork!这不免让人以为是child process从#include处开始执行,所以也执行了printf("fork!"); 语句。

其实不然,出现这种问题的原因在于:

这就跟Printf的缓冲机制有关了,printf某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里了,并没有实际的写到屏幕上 。但是,只要看到有\n, 则会立即刷新stdout,因此就马上能够打印了.

mian函数(parent process)运行了printf("fork!") 后, "fork!"仅仅被放到了缓冲里,再运行到fork时,缓冲里面的 AAAAAA 被子进程(child process)继承了,因此在子进程度stdout缓冲里面就也有了"fork!"。所以,你最终看到的会是 "fork!" 被printf了2次!!!! 而mian函数(parent process)运行 printf("fork!\n")后,"fork!" 被立即打印到了屏幕上,之后fork到的子进程(child process)里的stdout缓冲里不会有"fork!"内容 因此你看到的结果会是"fork!" 被printf了1次!!!!

posted on   kona  阅读(1340)  评论(0编辑  收藏  举报
编辑推荐:
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
阅读排行:
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee
· 用 DeepSeek 给对象做个网站,她一定感动坏了
· .NET 8.0 + Linux 香橙派,实现高效的 IoT 数据采集与控制解决方案
· DeepSeek处理自有业务的案例:让AI给你写一份小众编辑器(EverEdit)的语法着色文件
< 2025年2月 >
26 27 28 29 30 31 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 27 28 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示