为了账号安全,请及时绑定邮箱和手机立即绑定

“fork()”之后的printf异常

“fork()”之后的printf异常

12345678_0001 2019-06-01 16:23:58
“fork()”之后的printf异常操作系统:Linux,语言:纯C我正在学习一般的C编程,以及UNIX下的特殊情况下的C编程。我发现了一种奇怪的行为printf()函数在使用fork()打电话。电码#include <stdio.h>#include <system.h>int main(){     int pid;     printf( "Hello, my pid is %d", getpid() );     pid = fork();     if( pid == 0 )     {             printf( "\nI was forked! :D" );             sleep( 3 );     }     else     {             waitpid( pid, NULL, 0 );             printf( "\n%d was forked!", pid );     }     return 0;}输出量Hello, my pid is 1111I was forked! :DHello, my pid is 11112222 was forked!为什么第二个“Hello”字符串出现在子程序的输出中?是的,这正是父母在开始时打印的,父母的pid.但!如果我们把\n字符在每个字符串的末尾,我们得到预期的输出:#include <stdio.h>#include <system.h>int main(){     int pid;     printf( "Hello, my pid is %d\n", getpid() ); // SIC!!     pid = fork();     if( pid == 0 )     {             printf( "I was forked! :D" ); // removed the '\n', no matter             sleep( 3 );     }     else     {             waitpid( pid, NULL, 0 );             printf( "\n%d was forked!", pid );     }     return 0;}输出量:Hello, my pid is 1111I was forked! :D2222 was forked!为什么会发生这种事?它是正确的行为,还是一个错误?
查看完整描述

3 回答

?
繁星淼淼

TA贡献1775条经验 获得超11个赞

原因是如果没有\n在格式字符串的末尾,该值不会立即打印到屏幕上。相反,它是在进程中缓冲的。这意味着它实际上是在分叉操作之后才被打印出来的,因此您需要打印两次。

添加\n虽然强制缓冲区被刷新并输出到屏幕上。这种情况发生在分叉之前,因此只打印一次。

您可以通过使用fflush方法。例如

printf( "Hello, my pid is %d", getpid() );fflush(stdout);


查看完整回答
反对 回复 2019-06-01
?
慕娘9325324

TA贡献1783条经验 获得超4个赞

fork()有效地创建流程的副本。如果,在打电话之前fork(),它具有缓冲的数据,父数据和子数据都将具有相同的缓冲数据。下一次,当它们中的每一个做一些事情来刷新它的缓冲区时(例如,在终端输出的情况下打印换行符),您将看到除了该进程产生的任何新输出之外,缓冲的输出。因此,如果要在父级和子级中同时使用stdio,那么您应该fflush在分叉之前,要确保没有缓冲的数据。

通常,孩子只被用来调用exec*功能。因为这取代了完整的子进程映像(包括任何缓冲区),所以在技术上没有必要fflush如果这真的是你要在孩子身上做的所有事情。但是,如果可能有缓冲的数据,那么在处理EXEC失败时应该小心。特别是,避免使用任何stdio函数将错误打印到stdout或stderr(write),然后打电话给_exit(或_Exit)而不是打电话exit或者只是返回(这将刷新任何缓冲输出)。或者用叉子前冲一下来避免这个问题。


查看完整回答
反对 回复 2019-06-01
  • 3 回答
  • 0 关注
  • 801 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信