unix环境高级编程读书笔记: 一个fork示例的理解

书中示例代码如下:

#include "apue.h"

int glob=6;
char buf[]="a write to stdout\n";

int main(void)
{
    int var;
    pid_t pid;

    var=88;
    if(write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf) -1)
        err_sys("write error");
    printf("write error");

    if((pid=fork()) < 0)
        err_sys("fork error");
    else if(pid == 0)
    {
        glob++;
        var++;
    }
    else
    {
        sleep(2);
    }
    printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
    exit(0);
}


在终端输出如下:

$ ./a.out
a write to stdout
before fork
pid=430, glob=7, var=89
pid=429, glob=6, var=88
$./a.out >temp.out #输出重定向
a write to stdout
before fork
pid=430, glob=7, var=89
before fork
pid=429, glob=6, var=88

问1:为什么write只输出一次?

答:只进程执行的是fork后的代码,而不是从头开始执行。fork后,子进程共享父进程的数据段、代码段、堆栈段。文件表项属于栈段,所以也被复制了。同样缓冲,也被复制了。但由于write系统调用没有缓冲,所以,子进程复制的缓冲区里,没有此数据,即:buf。所以,子进程输出时,也没有输出此数据。

问2:为什么“befork fork"在第一个命令输出了一次,在第二个命令输出了两次。

答:标准IO是有缓冲的。但标准输出连接到终端时(输出到终端),是行缓冲。否则,是全缓冲。对于第一个命令:标准输出连接到终端,是行缓冲。由于输出中添加了换行符,所以,输出输出到缓冲区后,缓冲区被flush了。即,缓冲区为空。子进程复制的缓冲区的时候,缓冲区为空。所以,子进程输出的,就是在fork之后的printf里的数据。即:

"pid=430, glob=7, var=89\n"

对于第二个命令:标准输出被重定向至文件,此时,便是全缓冲。只有当缓冲区满,或关闭程序的时候才执行写操作,即是把数据输出到文件。子进程在复制父进程的各种数据的时候,在子进程的fork前,”before fork“仍在缓冲区中,子进程变回把缓冲区中的数据,即:”before fork“复制到自己的缓冲区。所以,子进程输出的是,”before fork“和fork之后的printf里的数据。输出的全部数据即是:

"before fork\npid=430, glob=7, var=89\n"

不管在什么情况下,父进程调用了什么printf,就输出对应的数据。不受影响。受这种影响的是子进程。


不管能不能对大家有帮助,但是写下来,防止将来遗忘总是极好的。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值