Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 父级过早终止时的子级反转输出_C_Unix_Exec_Fork_Signals - Fatal编程技术网

C 父级过早终止时的子级反转输出

C 父级过早终止时的子级反转输出,c,unix,exec,fork,signals,C,Unix,Exec,Fork,Signals,这是我试图实现的一些伪代码: 叉子 在子级中,将输出描述符复制到文件,然后执行不同的程序 在parent中,在一段时间后杀死孩子 问题是,在我杀死子文件后,输出文件是空的,即使子文件在某个阶段写入了它。我做错了什么?我不想等待孩子,但我也不想让它反转已经写入文件的内容。如果你的孩子因信号而死亡,它将不会刷新任何缓冲区,这就是你看不到任何输出的原因。这是有解决办法的 处理信号并刷新缓冲区 使用无缓冲I/O(应避免此情况) 同步子对象和父对象(使用管道)(以便父对象知道杀死子对象是安全的) 当然

这是我试图实现的一些伪代码:

叉子

在子级中,将输出描述符复制到文件,然后执行不同的程序

在parent中,在一段时间后杀死孩子


问题是,在我杀死子文件后,输出文件是空的,即使子文件在某个阶段写入了它。我做错了什么?我不想等待孩子,但我也不想让它反转已经写入文件的内容。

如果你的孩子因信号而死亡,它将不会刷新任何缓冲区,这就是你看不到任何输出的原因。这是有解决办法的

  • 处理信号并刷新缓冲区
  • 使用无缓冲I/O(应避免此情况)
  • 同步子对象和父对象(使用管道)(以便父对象知道杀死子对象是安全的)
当然,第三种选择是相当愚蠢的:孩子向父母发出信号可以简单地退出

编辑 根据编辑的问题和评论

stdio
(printf、fwrite等),出于I/O效率的考虑,使用了一些缓冲区。也就是说,当您执行一个简单的写操作时,低级操作不会立即发生。数据被复制到某个缓冲区,之后,当库认为有必要时(满缓冲区或其他东西),缓冲区将被刷新—将写入内容

现在,当程序调用
exit(3)
(正常进程终止)时,发生的事情之一是
stdio
缓冲区被刷新。如果一个程序由于一个信号而死机,
stdio
缓冲区不会被刷新,内存只会被操作系统占用


如果你不能控制你执行的程序(比如说你是一个shell),你就不能确定如果你杀死它们,它们会做什么。也就是说,这不是你的责任。然而,如果你确实控制了它们(你说了一些关于管道的事情),你可以简单地通过管道发出信号,让孩子们调用
exit(3)

kill
做你想做的事情(将
SIGINT
发送到
childpid
)。你到底有什么问题?哦,好的。我将文件描述符复制到一个文件中,以便我的子进程写入,然后在子进程中执行。这是可行的,但我的问题是,一旦我杀死了这个孩子,输出文件就会变成空的。如果我不杀死它,那么它从我的子进程中有正确的输出,但是如果我杀死它,那么它就什么都没有了(即使在我杀死它之前它已经将内容写入文件)。在我杀死输出流之前,我需要告诉孩子关闭输出流吗?请编辑你的问题(以及它的标题),以准确地解释正在发生的事情以及你想要发生的事情。如果你需要孩子完成某件事,不等待他正确完成是没有意义的。我不想等他完成,但我也不想让他逆转已经完成的事情(写入文件),所以我不明白他在做什么。我会编辑这个问题。谢谢!如果我不想更改正在执行的程序,我想做以下哪一项?@Sam嗯,既然你不想修改你执行的程序,很难说。为什么不让它正常退出呢?如果它不应该正常退出,你怎么知道什么时候该杀了它?我需要用户能够向它发送信号来杀了它,但我不想让它擦除它已经做过的事情。老实说,我真的不明白为什么它会抹去它已经做过的事情。你能解释一下关于刷新缓冲区的更多信息吗?为什么这是必要的?我能在父母身上做吗?你为什么说孩子“正在抹去已经做过的事情”?如果事实上您看到文件中的数据在孩子被杀死时被截断,那将是非常了不起的。在你杀死孩子之前,你怎么知道他做了什么呢?@Sam:正确的方法不是
sleep(1)
,而是先用
sigprogmask
阻止
SIGCHLD
,然后发送
SIGINT
,使用
sigtimedwait
等待
SIGCHLD
,使用
waitpid
WNOHANG
查看它是否已退出,如果未退出,则发送
SIGKILL
。这样你就避免了在你的程序中引入不必要的延迟——用户肯定讨厌这种延迟!