少于 1 分钟阅读 次阅读

概要:通过 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

留下评论