Fork 系统调用期间的文件描述符处理

问题描述 投票:0回答:1

我是 POSIX 世界的新手,我试图了解 fork 系统调用在 C 中的工作原理,特别是它如何在父级到子级之间复制文件描述符和缓冲区。具体来说这两种情况:

案例一: 我有一个简单的程序可以打印一些东西

printf "start"
fork
parent:
  print something
child 
  print something

这最终会打印“start”一次,然后打印父块和子块。这意味着 fork 在复制 I/O 缓冲区之前先刷新它们。

案例2: 相同的程序,但现在我正在写入文件而不是标准输出。 该文件导致开始打印两次,这对我来说很奇怪。 fork 是否只刷新标准缓冲区而不刷新文件缓冲区?

用于测试的程序:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <fcntl.h>

int main() {
    pid_t pid;
    FILE *fd;

    // Open a file in writing mode
    fd = fopen("filename.txt", "w");

    // Write some text to the file
    fprintf(fd, "Started\n");

    // Create a child process
    pid = fork();

    if (pid < 0) {
        // Fork failed
        fprintf(stderr, "Fork failed\n");
        fclose(fd);
        return 1;
    } else if (pid == 0) {
        // This is the child process
        const char *child_message = "Hello from the child process!\n";
        fprintf(fd, child_message);
        fclose(fd); // Close the file descriptor in the child process
        exit(0);
    } else {
        // This is the parent process
        const char *parent_message = "Hello from the parent process!\n";
        fprintf(fd, parent_message);

        // Wait for the child process to complete
        wait(NULL);

        // Write a final message from the parent
        const char *completion_message = "Child process completed.\n";
        fprintf(fd, completion_message);

        fclose(fd); // Close the file descriptor in the parent process
    }

    return 0;
}
c linux fork posix file-descriptor
1个回答
0
投票

首先,

fork()
不会刷新缓冲区。

其次,牢记这两点

  1. 当且仅当输出流连接到终端设备时,它始终是行缓冲的。比如

    stdout
    stderr
    ,都是这种情况。否则输出流将被完全缓冲。

  2. fork()
    将所有内存从父级复制到子级。 (为了降低复杂性,我们不在这里讨论
    COW

现在回到你的问题。

在您的第一个示例中,只有一个“开始 打印出",是因为在

fork()
之前,
stdout
的缓冲区已经被flush了(行缓冲),复制到子进程时缓冲区已经空无一物了。

在第二个示例中,两个“开始 ” 被打印。这是因为在

fork()
之前,常规文件的缓冲区还没有被刷新(完全缓冲)。包含“Start " 被复制到子进程。

© www.soinside.com 2019 - 2024. All rights reserved.