当前位置:   article > 正文

Linux fork函数具体图解-同一时候分析一道腾讯笔试题

fork函数输出的时候前面有【root@localhost test】#

原创blog。转载请注明出处

头文件:

#include<unistd.h>
#include<sys/types.h>
函数原型:
pid_t fork( void);
(pid_t 是一个宏定义,事实上质是int 被定义在#include<sys/types.h>中)
返回值: 若成功调用一次则返回两个值。子进程返回0。父进程返回子进程ID。否则,出错返回-1
注意。子进程是父进程的副本,拷贝父进程的数据空间,堆栈等资源。

父子进程不共享上述资源。


每运行一次fork()函数,会返回两次。一次是在父进程,一次是在子进程,两次的返回值不一样。


我们来看一个简单的样例

  1. #include<unistd.h>
  2. #include<sys/types.h>
  3. #include<stdio.h>
  4. #include<stdlib.h>
  5. int main(int argc, char ** argv )
  6. {
  7. pid_t result = fork();
  8. if(result < 0)
  9. {
  10. printf("Error");
  11. }
  12. else if(result == 0)
  13. {
  14. printf("From the son");
  15. }
  16. else
  17. {
  18. printf("From the father");
  19. }
  20. }

输出

  1. From the son
  2. From the father

能够看到,父子进程都同一时候运行了这段代码。

能够这么理解,子进程拷贝父进程的全部代码。和堆栈,然后从fork()的下一行,子进程运行

再看一个样例

代码

  1. #include<unistd.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. int main(int argc, char ** argv )
  5. {
  6. int i;
  7. for(i = 0;i < 2;i++)
  8. {
  9. fork();
  10. printf("%d\n",i);
  11. }
  12. }


然后我们编译运行
运行的结果是
[root@localhost test]# gcc -o first first.c 
[root@localhost test]# ./first 
0
1
1
0
1
1


为了便于分析,我们每次都输出当前进程的ppid(父进程)以及当前进程的pid

  1. #include<unistd.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. int main(int argc, char ** argv )
  5. {
  6. int i;
  7. for(i = 0;i < 2;i++)
  8. {
  9. fork();
  10. printf("%d PPID:%d PID:%d\n",i,getppid(),getpid());
  11. }
  12. }

结果

[root@localhost test]# ./first
0 PPID:4984 PID:4985
1 PPID:4985 PID:4986
1 PPID:4984 PID:4985
0 PPID:4424 PID:4984
1 PPID:4984 PID:4987
1 PPID:4424 PID:4984
先分析PID。一共同拥有4种,所以一共同拥有4984,4985,4986,4987四个进程,所以4424是最開始的进程(main)的父进程,所以。最開始的进程是4984
然后根据pid来梳理进程的父子关系
依照子进程->父进程
4986->4985->4984->4424
4987->4984->4424

所以依照这个关系,我们绘图来分析比較直观

当中,输出的顺序依照红色圈中顺序来输出

由图能够看出,在我的这个CentOS系统中,子进程比父进程先运行,运行顺序在不同系统中不一样。所以编程的时候应当不依赖运行某一个系统的顺序

然后,我们来分析一道经典的笔试面试题

  1. for(i = 0;i < 2;i++)
  2. {
  3. fork();
  4. printf("%d\n",i);
  5. }
  6. }

  1. for(i = 0;i < 2;i++)
  2. {
  3. fork();
  4. printf("%d",i);
  5. }
  6. }

各输出了几个0,几个1

对于前者

输出是

  1. 0
  2. 1
  3. 1
  4. 0
  5. 1
  6. 1

对于后者

输出是

01010101
对于前者,在上面已经进行了图解。所以不难理解。对于后者,不少同学会非常奇怪,为什么输出了4个0,4个1?

原因是:C语言中,printf函数假设遇到\n,会马上输出缓冲区内全部内容,假设没有\n,会先输出到缓冲区内。等待输出

我们继续绘图来分析,



这里在详解下:能够这么理解,每次printf的时候,是把本进程的printf缓冲区,增加到总的printf缓冲区(这样的说法可能不严谨)。比方到红色圈圈3的时候。4985本身在红色圈圈1的时候缓冲区已经有0了。那么再增加1,则本身进程的缓冲区为01,那么增加到printf总的缓冲区就是0101

原创blog,转载请注明出处



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/210559
推荐阅读
相关标签
  

闽ICP备14008679号