【问题标题】:Is it legit to share the buffer used for stdio buffering between parent and child process?在父进程和子进程之间共享用于 stdio 缓冲的缓冲区是否合法?
【发布时间】:2014-04-07 18:29:54
【问题描述】:

我想知道为 stdio 流缓冲分配一个缓冲区并将其与setvbuf(在fork 之前)一起使用是否合法,其中缓冲区是匿名的mmap-“已分配”一块内存共享父子进程之间?

假设这两者是同步的,我是否可以假设结果会是正常的,或者我应该不惜一切代价避免这种情况?

【问题讨论】:

  • 我认为这还需要进程间互斥锁,我不知道 stdio 会使用它。只是一个想法-我不知道:)。

标签: c fork mmap stdio sus


【解决方案1】:

你不应该这样做。您的 C 库将假定 进程 具有对标准 IO 缓冲区的独占访问权限,并且只会在该进程的 线程 之间进行调解,毫无疑问使用非匿名互斥锁mmap。因此,如果更改该缓冲区空间,您将面临未定义行为的风险,就像您自己重写它一样。

但是,一个更好的问题是,您到底为什么要这样做?为什么不让缓冲区/not/共享(例如使用malloc()分配),那么一切都会正常。

【讨论】:

  • 不确定您提出的问题是否更好。你假设我没有理由,但我有。无论如何都赞成和接受。谢谢。知道我应该避免它就足够了。此外,父级不会更改缓冲区,而子级可以。这就是为什么这个问题首先有意义(以及我在第二段中提到的情况)。
  • 这是一个更好的问题,因为我想不出有什么用处,因此我对你的想法很感兴趣。
  • 分叉的代码保护着一段特定的代码。如果缓冲区可以在父级和子级之间正确共享,我将能够简单地继续输出到我从父级打开的 stdio 流。由于情况并非如此,我不能(因为它可能会散布输出,或者在最坏的情况下会破坏任何一个进程的某些内容)。
  • 最好要么使用线程(如果你不使用exec)或者用管道来做这件事。
  • re: 线程...它仍然会崩溃。关键是这是为了强调和测试一些核心代码。预计/预期会发生崩溃(我也在使用 AddressSanitizer 构建它)。因此,最好在崩溃时分叉到另一个不会影响父进程的进程。是的,现在是管道。不过,我曾希望有一个更简单的解决方案。再次感谢。
【解决方案2】:

这取决于您的 C 库实现存储管理缓冲区的控制信息的位置。

如果所有用于控制线程并发写入的控制信息都存储在缓冲区本身,那么一切都可以正常工作。

但是,如果该控制信息存储在其他地方,它将在进程之间复制。两个不同进程中的 libc 实例不会意识到另一个进程写入缓冲区或刷新缓冲区,从而导致混乱。

即使您的 libc 实现在此设置下运行良好,我还是强烈建议您不要这样做。毕竟setvbuf()的语义是设置一个缓冲区,而不是存储缓冲区控制信息。

【讨论】:

  • ...也就是说我不能做出这样的假设。谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-04-25
  • 1970-01-01
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多