You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下如何实现父子进程的文件字节级读写操作?

Linux下父子进程共享读取文件并分别写入的实现与代码修正

核心原理说明

Linux中调用fork()创建子进程后,父子进程会共享已打开的文件描述符,包括文件的当前偏移量。这意味着当父/子进程调用read()读取文件时,会自动推进共享的偏移量,两个进程不会重复读取同一个字节,而是受系统调度影响交替读取文件后续内容,最终共同完成整个文件的读取,再分别写入各自的目标文件。

原代码存在的问题

  1. 语法拼写错误:

    • unisigned long i; 拼写错误,应为unsigned long i;
    • 声明了fdrt但未使用,反而使用了未声明的fdrd,编译直接报错
    • 空循环if(i=0;i<50000;i++);是错误写法:这里是赋值操作i=0而非判断,且循环体为空,既达不到模拟延迟的效果还会浪费CPU资源
  2. 资源泄漏与不规范写法:

    • 使用老式main函数写法,不符合C标准,应改为int main(int argc, char *argv[])
    • 打开的文件描述符未调用close()关闭,会造成资源泄漏
    • 未对write()的返回值做错误检查,无法感知写入失败的情况
  3. 逻辑可维护性问题:

    • 变量命名模糊(如fdwt2、fdwt3),建议根据用途命名提升可读性
    • 循环使用for(;;),改为while(1)逻辑更清晰

修正后的完整代码

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

// 错误处理函数,简化重复代码
void handle_error(const char *msg) {
    perror(msg);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
    int fd_read, fd_parent_write, fd_child_write;
    char c;
    const char parent_mark = 'P';
    const char child_mark = 'C';
    pid_t pid;

    // 参数检查:需要传入 源文件、父进程目标文件、子进程目标文件 三个参数
    if (argc != 4) {
        fprintf(stderr, "Usage: %s <src_file> <parent_dst> <child_dst>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // 打开源文件(只读)
    if ((fd_read = open(argv[1], O_RDONLY)) == -1) {
        handle_error("Failed to open source file");
    }

    // 创建父进程目标文件(读写权限0666)
    if ((fd_parent_write = creat(argv[2], 0666)) == -1) {
        handle_error("Failed to create parent destination file");
    }

    // 创建子进程目标文件(读写权限0666)
    if ((fd_child_write = creat(argv[3], 0666)) == -1) {
        handle_error("Failed to create child destination file");
    }

    printf("Parent: creating child process\n");
    pid = fork();
    if (pid == -1) {
        handle_error("Failed to fork child process");
    }

    if (pid == 0) {
        // 子进程逻辑:读取源文件,写入子进程目标文件
        printf("Child process starts, id=%d\n", getpid());
        while (1) {
            ssize_t read_bytes = read(fd_read, &c, 1);
            if (read_bytes == 0) {
                // 读取到文件末尾,退出循环
                break;
            } else if (read_bytes == -1) {
                handle_error("Child process read failed");
            }

            // 写入标记到标准输出(便于观察调度情况)
            if (write(STDOUT_FILENO, &child_mark, 1) == -1) {
                handle_error("Child process write mark failed");
            }
            // 写入内容到目标文件
            if (write(fd_child_write, &c, 1) == -1) {
                handle_error("Child process write to file failed");
            }
        }

        // 关闭文件描述符
        close(fd_read);
        close(fd_child_write);
        exit(EXIT_SUCCESS);
    } else {
        // 父进程逻辑:读取源文件,写入父进程目标文件
        printf("Parent starts, id=%d\n", getpid());
        while (1) {
            ssize_t read_bytes = read(fd_read, &c, 1);
            if (read_bytes == 0) {
                // 读取到文件末尾,退出循环
                break;
            } else if (read_bytes == -1) {
                handle_error("Parent process read failed");
            }

            // 写入标记到标准输出(便于观察调度情况)
            if (write(STDOUT_FILENO, &parent_mark, 1) == -1) {
                handle_error("Parent process write mark failed");
            }
            // 写入内容到目标文件
            if (write(fd_parent_write, &c, 1) == -1) {
                handle_error("Parent process write to file failed");
            }
        }

        // 等待子进程结束
        wait(NULL);
        // 关闭文件描述符
        close(fd_read);
        close(fd_parent_write);
        exit(EXIT_SUCCESS);
    }
}

使用说明

  1. 编译代码:gcc -o file_split file_split.c
  2. 执行程序:./file_split a.txt b.txt c.txt
    • a.txt是源文件,b.txt会被父进程写入内容,c.txt会被子进程写入内容
  3. 执行时标准输出会打印P(父进程读取标记)和C(子进程读取标记),可以直观看到父子进程的调度情况

内容的提问来源于stack exchange,提问作者zeyzey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 01:55:32