C 在父进程和子进程之间共享用于stdio缓冲的缓冲区合法吗?

C 在父进程和子进程之间共享用于stdio缓冲的缓冲区合法吗?,c,fork,mmap,stdio,sus,C,Fork,Mmap,Stdio,Sus,我想知道为stdio流缓冲分配一个缓冲区并与setvbuf(在fork之前)一起使用是否合法,其中缓冲区是父进程和子进程之间共享的匿名mmap-“分配的”内存块 假设两者是同步的,我是否可以假设结果是合理的,或者我应该不惜一切代价避免这样做?你不应该这样做。您的C库将假定该进程以独占方式访问标准IO缓冲区,并且只在该进程的线程之间进行调解,毫无疑问,它使用的互斥对象不是匿名mmap。所以,如果缓冲区空间被改变,您将面临未定义行为的风险,就像您自己在上面写一样 然而,一个更好的问题是,你到底为什么

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


假设两者是同步的,我是否可以假设结果是合理的,或者我应该不惜一切代价避免这样做?

你不应该这样做。您的C库将假定该进程以独占方式访问标准IO缓冲区,并且只在该进程的线程之间进行调解,毫无疑问,它使用的互斥对象不是匿名
mmap
。所以,如果缓冲区空间被改变,您将面临未定义行为的风险,就像您自己在上面写一样


然而,一个更好的问题是,你到底为什么要这样做?为什么不将缓冲区设为/not/shared(例如,通过使用
malloc()
来分配它),那么一切都会正常工作。

您不应该这样做。您的C库将假定该进程以独占方式访问标准IO缓冲区,并且只在该进程的线程之间进行调解,毫无疑问,它使用的互斥对象不是匿名
mmap
。所以,如果缓冲区空间被改变,您将面临未定义行为的风险,就像您自己在上面写一样


然而,一个更好的问题是,你到底为什么要这样做?为什么不将缓冲区设为/not/shared(例如,通过使用
malloc()
分配它),那么一切都会正常工作。

这取决于C库的实现将管理缓冲区的控制信息存储在何处

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

但是,如果该控制信息存储在其他地方,它将在进程之间复制。两个不同进程中的libc实例在另一个进程写入或刷新缓冲区时将无法实现,随后将出现混乱


即使您的libc实现可以很好地使用此设置,我也强烈建议您不要使用它。毕竟,
setvbuf()
的语义是设置一个缓冲区,而不是存储缓冲区控制信息。

这取决于您的C库实现在何处存储管理缓冲区的控制信息

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

但是,如果该控制信息存储在其他地方,它将在进程之间复制。两个不同进程中的libc实例在另一个进程写入或刷新缓冲区时将无法实现,随后将出现混乱


即使您的libc实现可以很好地使用此设置,我也强烈建议您不要使用它。毕竟,
setvbuf()
的语义是设置缓冲区,而不是存储缓冲区控制信息。

我认为这也需要进程间互斥,我不知道stdio会使用。不过我只是想一想——我不知道:)。我想这也需要进程间互斥,我不知道stdio会使用这些互斥。只是一个想法-我不知道:)。。。。也就是说我不能做出这样的假设。谢谢也就是说我不能做出这样的假设。谢谢。我不确定你提出的问题是否更好。你以为我没有理由,但我有。无论如何,投票和接受。谢谢知道我应该避免它就足够了。此外,父级不会更改缓冲区,而子级可能会更改缓冲区。这就是为什么这个问题首先是有意义的(以及我在第二段中提到的情况)。这是一个更好的问题,因为我想不出在什么情况下它会有用,因此我对您的想法感兴趣。forks的代码是保护一段特定的代码。如果缓冲区可以在父级和子级之间正确共享,我就可以继续输出到从父级打开的stdio流。由于情况并非如此,我无法(因为它可能会分散输出,或者在最坏的情况下会损坏任何一个进程的某些内容)。最好使用线程(如果您不使用
exec
),或者使用管道进行硬处理。re:threads。。。它仍然会崩溃。关键是,这是为了强调和测试一些核心代码。预计会发生崩溃(除其他外,我还使用AddressSanitarizer构建了此功能)。因此,当崩溃时,最好转到另一个不影响父进程的进程。是的,现在是。不过,我希望有一个更简单的解决方案。再次感谢。我不确定你提出的问题是否更好。你以为我没有理由,但我有。无论如何,投票和接受。谢谢知道我应该避免它就足够了。此外,父级不会更改缓冲区,而子级可能会更改缓冲区。这就是为什么这个问题首先是有意义的(以及我在第二段中提到的情况)。这是一个更好的问题,因为我想不出在什么情况下它会有用,因此我对您的想法感兴趣。forks的代码是保护一段特定的代码。如果缓冲区可以在父级和子级之间正确共享,我就可以继续输出到从父级打开的stdio流。由于情况并非如此,我无法(因为它可能会分散输出,或者在最坏的情况下会损坏任何一个进程的某些内容)。最好使用线程(如果您不使用
exec
),或者使用管道进行硬处理。re:threads。。。它仍然会崩溃。关键是,这是为了强调和测试一些核心代码。预计会发生崩溃(除其他外,我还使用AddressSanitarizer构建了此功能)。那就太多了