复制文件描述符后仍共享文件偏移
概要:通过 fork 写入文件的示例,说明复制文件描述符后父子进程共享同一 struct file 与文件偏移;并对比 fork/dup/open 在偏移共享上的区别及设计出发点。
1 示例
代码:
if(fork() == 0) {
write(1, "hello ", 6);
exit();
} else {
wait();
write(1, "world\n", 6);
}
执行过程:
fork 前
FD1 -> struct file A
offset = 0
fork 后
父FD1 -> struct file A
子FD1 -> struct file A (共享)
子进程写入
write("hello ")
offset: 0 -> 6
父进程 wait 后写入
write("world")
offset: 6 -> 12
最终文件:
hello world
如果 offset 不共享,结果会是:
world
因为父进程会从 0 重新写。
2 设计出发点
考虑 shell 命令:
(echo hello; echo world) > output.txt
执行方式:
fork
├── child1: echo hello
└── child2: echo world
两个 echo 都写到同一个文件描述符:
FD1 -> output.txt
因为偏移共享,所以输出不会覆盖:
hello
world
这就是 Unix 设计的优势:
多进程顺序写文件时,不需要显式 seek。
3 与重新 open 同一个文件的区别
最容易被忽略的是:
即使打开的是同一个文件,只要是 open 得到的 FD,偏移就不共享。
示例:
fd1 = open("a.txt", O_WRONLY);
fd2 = open("a.txt", O_WRONLY);
此时:
FD1 -> struct file A (offset 0)
FD2 -> struct file B (offset 0)
写入:
write(fd1, "hello", 6);
write(fd2, "world", 6);
结果:
world
因为第二次写从 offset 0 覆盖。
4 fork / dup / open 三者对比
| 操作 | 是否共享 struct file | 是否共享 offset |
|---|---|---|
| fork | 是 | 是 |
| dup | 是 | 是 |
| open | 否 | 否 |
留下评论