栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

“ fork()”之后的printf异常

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

“ fork()”之后的printf异常

我注意到这

<system.h>
是一个非标准头文件;我将其替换为
<unistd.h>
干净地编译的代码。

当程序的输出进入终端(屏幕)时,它是行缓冲的。当程序的输出进入管道时,将被完全缓冲。您可以通过标准C函数

setvbuf()
以及
_IOFBF
(完全缓冲),
_IOLBF
(行缓冲)和
_IONBF
(无缓冲)模式来控制缓冲模式。

您可以通过将程序的输出传递到,在修改后的程序中进行演示

cat
。即使
printf()
字符串末尾有换行符,您也会看到重复信息。如果直接将其发送到终端,则只会看到很多信息。

这个故事的寓意是要小心

fflush(0);
在分叉之前调用所有I / O缓冲区。


按要求进行逐行分析(大括号等已删除-标记编辑器已删除了前导空格):

  1. printf( "Hello, my pid is %d", getpid() );
  2. pid = fork();
  3. if( pid == 0 )
  4. printf( "nI was forked! :D" );
  5. sleep( 3 );
  6. else
  7. waitpid( pid, NULL, 0 );
  8. printf( "n%d was forked!", pid );

分析:

  1. 将“您好,我的pid是1234”复制到缓冲区中以进行标准输出。由于末尾没有换行符,并且输出以行缓冲模式(或全缓冲模式)运行,因此终端上没有任何内容。
  2. 为我们提供了两个单独的过程,标准输出缓冲区中的材料完全相同。
  3. 孩子有
    pid == 0
    并执行第4和5行;父对象的值为非零
    pid
    (两个进程之间的几个差异之一-从
    getpid()
    和返回的值
    getppid()
    是另外两个)。
  4. 将一个换行符和“我被分叉!:D”添加到子级的输出缓冲区。输出的第一行出现在终端上;其余的保留在缓冲区中,因为输出是行缓冲的。
  5. 一切暂停3秒钟。此后,孩子通常通过main的返回返回。此时,标准输出缓冲区中的剩余数据将被清除。由于没有换行符,因此将输出位置留在行尾。
  6. 父母来了。
  7. 父母等待孩子完成死亡。
  8. 父母添加了一个换行符,并且“派生了1345!” 到输出缓冲区。在子代生成的行不完整之后,换行符将“ Hello”消息刷新到输出。

父级现在通常通过main的结尾处的返回退出,并且清除了剩余数据;由于末尾仍然没有换行符,因此光标位置在感叹号之后,并且shell提示出现在同一行上。

我看到的是:

Osiris-2 JL: ./xxHello, my pid is 37290I was forked! :DHello, my pid is 3729037291 was forked!Osiris-2 JL: Osiris-2 JL:

PID号不同-但整体外观清晰。在

printf()
语句的末尾添加换行符(这很快成为标准做法)会极大地改变输出:

#include <stdio.h>#include <unistd.h>int main(){    int pid;    printf( "Hello, my pid is %dn", getpid() );    pid = fork();    if( pid == 0 )        printf( "I was forked! :D %dn", getpid() );    else    {        waitpid( pid, NULL, 0 );        printf( "%d was forked!n", pid );    }    return 0;}

我现在得到:

Osiris-2 JL: ./xxHello, my pid is 37589I was forked! :D 3759037590 was forked!Osiris-2 JL: ./xx | catHello, my pid is 37594I was forked! :D 37596Hello, my pid is 3759437596 was forked!Osiris-2 JL:

请注意,当输出到达终端时,它是行缓冲的,因此“
Hello”行出现在之前,

fork()
并且只有一个副本。当输出通过管道传递到时
cat
,它已被完全缓冲,因此在
fork()
和两个进程的要刷新的缓冲区中都有“
Hello”行之前,什么都没有出现。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/400933.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号