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返回。

#include <unistd.h>
#include <sys/types.h> main ()
{
pid_t pid;
printf("hello!\n");
pid=fork(); if (pid < )
printf("error in fork!");
else if (pid == )
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");

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

#include <unistd.h>
#include <sys/types.h> main ()
{
pid_t pid;
printf("fork!"); //printf("fork!\n") pid=fork(); if (pid < )
printf("error in fork!\n");
else if (pid == )
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次!!!!

最后这个打印两遍fork的问题,在APUE上面有讲过,在APUE上8.3节 (第三版中文版是184页 ).当时看了就忘了,前几天刚好碰到这么个问题,我不得不怀疑fork到底从哪里开始执行,所幸这个帖子救了我...

linux中fork--子进程是从哪里开始运行的更多相关文章

  1. 用 set follow-fork-mode child即可。这是一个 gdb 命令,其目的是告诉 gdb 在目标应用调用fork之后接着调试子进程而不是父进程,因为在 Linux 中fork系统调用成功会返回两次,一次在父进程,一次在子进程

    GDB的那些奇淫技巧 evilpan 收录于 Security  2020-09-13  约 5433 字   预计阅读 11 分钟  709 次阅读  gdb也用了好几年了,虽然称不上骨灰级玩家,但 ...

  2. Linux中fork的秘密

    linux中fork()函数详解         一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以 ...

  3. linux中fork创建进程讲解(转)

    大家知道Linux中创建子进程的一个很好的方法是函数调用fork,但是很多初学者对fork的理解上可能有点困难.我们举个例子来看看fork的用法吧.         大家用fork的时候记住fork是 ...

  4. linux中fork, source和exec的区别

    转:linux中fork, source和exec的区别 shell的命令可以分为内部命令和外部命令. 内部命令是由特殊的文件格式.def实现的,如cd,ls等.而外部命令是通过系统调用或独立程序实现 ...

  5. 【转】linux 中fork()函数详解

    在看多线程的时候看到了这个函数,于是学习了下,下面文章写的通俗易懂,于是就开心的看完了,最后还是很愉快的算出了他最后一个问题. linux 中fork()函数详解 一.fork入门知识 一个进程,包括 ...

  6. Linux中fork()函数详解(转载)

    linux中fork()函数详解 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事, ...

  7. linux中fork()函数

    man fork: FORK() Linux Programmer's Manual FORK(2) NAME fork - create a child process SYNOPSIS #incl ...

  8. linux中fork()函数具体解释(原创!!实例解说)

     一.fork入门知识 一个进程,包含代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程差点儿全然同样的进程,也就是两个进程能够做全然同样的事,但假设初始參数或者传入的变量不 ...

  9. 【转】linux中fork()函数详解

    原文链接:http://blog.csdn.net/jason314/article/details/5640969#comments 总结:面宝P268 fork()的意思是进程从这里开始分叉,分成 ...

随机推荐

  1. shell习题第26题:监控mysql服务

    [题目要求] 假设mysql密码是123456. 写脚本监控mysql服务是否正常,比如是否可以执行show processlist,并检测一下当前的mysql服务是主还是从.如果是从,请判断他的主从 ...

  2. c#基础知识梳理(二)

    上期回顾 - https://www.cnblogs.com/liu-jinxin/p/10818256.html 一.变量 一个变量只不过是一个供程序操作的存储区的名字.在 C# 中,每个变量都有一 ...

  3. Opencl 学习笔记

    1. HelloWorld

  4. java毫秒级别定时器

    java每100毫秒执行一次 //每100毫秒秒执行一次 @Scheduled(fixedRate = 100) public void testScheduler() { System.out.pr ...

  5. JavaScript--Function对象(函数)的声明和作用域

    Funtion 封装了可重复使用的代码块对象,函数名是一个引用函数对象的变量 声明提前:在程序开始执行之前,将var 变量和function函数提前声明 但赋值并不会提前 它的三种创建方法: 创建1 ...

  6. Linux Centos7配置mysql8.0数据库

    本文转至:672530440 在此感谢博主,撒花!!! 本文主要从以下几个方面对自己在centos7 下安装mysql8过程做如下总结: CentOS7 安装mysql8 步骤: window下的Na ...

  7. 常用的bug管理工具

    1. QC(Quality Center)是原Mercury Interactive公司(现已被HP收购)生产的企业级基于WEB測试管理工具,须要安装配置IIS和数据库.系统资源消耗比較 大:功能非常 ...

  8. Linux——CentOS7安装gcc编译器详解 查看内核版本

    [root@localhost ~]# uname -a Linux localhost.localdomain 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:3 ...

  9. EditText编辑框

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  10. 【问题】Debian安装、配置sources.list、安装VMware Tools

    Debian安装: 我采用的是纯命令行安装方式.具体安装过程网上一大堆,不介绍了.需要强调一点,那个SSH Server必须选,否则像XShell这样的客户端不能访问Debian. 配置sources ...