Linux下如何实现父子进程的文件字节级读写操作?
Linux下父子进程共享读取文件并分别写入的实现与代码修正
核心原理说明
Linux中调用fork()创建子进程后,父子进程会共享已打开的文件描述符,包括文件的当前偏移量。这意味着当父/子进程调用read()读取文件时,会自动推进共享的偏移量,两个进程不会重复读取同一个字节,而是受系统调度影响交替读取文件后续内容,最终共同完成整个文件的读取,再分别写入各自的目标文件。
原代码存在的问题
语法拼写错误:
unisigned long i;拼写错误,应为unsigned long i;- 声明了
fdrt但未使用,反而使用了未声明的fdrd,编译直接报错 - 空循环
if(i=0;i<50000;i++);是错误写法:这里是赋值操作i=0而非判断,且循环体为空,既达不到模拟延迟的效果还会浪费CPU资源
资源泄漏与不规范写法:
- 使用老式
main函数写法,不符合C标准,应改为int main(int argc, char *argv[]) - 打开的文件描述符未调用
close()关闭,会造成资源泄漏 - 未对
write()的返回值做错误检查,无法感知写入失败的情况
- 使用老式
逻辑可维护性问题:
- 变量命名模糊(如
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); } }
使用说明
- 编译代码:
gcc -o file_split file_split.c - 执行程序:
./file_split a.txt b.txt c.txta.txt是源文件,b.txt会被父进程写入内容,c.txt会被子进程写入内容
- 执行时标准输出会打印
P(父进程读取标记)和C(子进程读取标记),可以直观看到父子进程的调度情况
内容的提问来源于stack exchange,提问作者zeyzey
相关产品推荐
相关产品推荐

