c -在fork()之后,子进程是否与父进程共享stdio流(FILE *)偏移量?



所以我知道,正如在fork手册中所述,派生的子进程有来自父进程的打开fd的副本,所以父进程和子进程共享文件偏移量。

Stdio流是建立在fd函数之上的,但它们包括每个进程唯一的缓冲区,所以在分叉的时候,子进程继承了那些FILE*,但是它们共享相同的缓冲区和相同的文件偏移量吗?

我已经搜索了手册和这个论坛,但没有找到任何关于FILE*,只有关于文件描述符。对不起,如果这个问题是重复的,但我没有找到它。

正如fork()手册中所述,以及您在帖子中所说:

子进程继承父进程的打开文件集的副本描述符。子文件中的每个文件描述符都引用相同的打开文件描述(参见open(2))作为相应的父目录中的文件描述符。这意味着这两个文件描述符共享打开文件状态标志、文件偏移量和信号驱动的I/O属性(参见F_SETOWN的描述)and F_SETSIG in fcntl(2) .

FILE是一个位于OS文件描述符数据结构之上的数据结构。它基本上是一个动态的内存分配,在分叉时从父进程复制到子进程。因此,此数据结构中的任何缓冲数据都将在子进程中复制。它们都可以在任何时候将它刷新到目标文件中。由于文件偏移量在父节点和子节点之间共享,这将在输出上触发重复打印。以下面的程序为例:

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
printf("String to be printed on stdout");
if (fork() == 0) {
// Child
fflush(stdout);

} else {
// Father
fflush(stdout);
wait(NULL);
}
}

当运行它时,我们可以看到两个打印结果来自最初从父进程调用的单个printf():

$ gcc try.c
$ ./a.out 
String to be printed on stdoutString to be printed on stdout$

当然,任何将来在child或father侧的打印都将在输出中混合,因为它们都将移动相同的底层文件偏移量。

NB: C库中的studio子系统的目标是通过使用I/O首先进入的中间缓冲区来最小化系统调用的数量。实际的系统调用是在没有选择的情况下触发的(需要清空缓冲区以将数据追加到输出文件中,查找操作超出了缓冲区当前映射的范围,显式刷新请求…)。因此,如果其中一个进程调用rewind()ftell(),这可能会导致实际的系统调用,也可能不会,这取决于调用进程中缓冲区的状态。只有当系统调用完成时,其他进程才会受到影响。库调用和等效的系统调用之间不存在1/1的对应关系。通常,库调用会比系统调用多(例如,多个fwrite()可能只触发一个write()系统调用)。

相关内容

  • 没有找到相关文章

最新更新