最近我在学习 Linux 进程间通信。但是我对管道机制的理解有些问题。
我知道管道是由父进程创建的一对文件,然后父进程将文件描述符传递给子进程,子进程就可以操作它们了。
但是由于子进程在 fork() 后调用 exec() 时会拥有一个全新的虚拟内存,那么为什么父进程可以把信息传递给子进程呢?我有什么遗漏的吗?
最近我在学习 Linux 进程间通信。但是我对管道机制的理解有些问题。
我知道管道是由父进程创建的一对文件,然后父进程将文件描述符传递给子进程,子进程就可以操作它们了。
但是由于子进程在 fork() 后调用 exec() 时会拥有一个全新的虚拟内存,那么为什么父进程可以把信息传递给子进程呢?我有什么遗漏的吗?
// pseudo-code:
// create the pipe
int pipe_end[2];
pipe(pipe_end);
// "back up" stdin
int save_in = dup(0);
// position the pipe to stdin for the benefit of the child
dup2(pipe_end[0], 0);
// start the child
fork() && exec();
// restore stdin
close(0);
dup2(save_in, 0);
// write to the child
write(pipe_end[1], ...);
信息不会传递给子进程 - 它是通过隐式约定完成的。父进程知道它应该将 fds 复制到 0、1、2 号槽中,而子进程知道要从这些描述符读取/写入。你说得对,在 exec 过程中确实没有任何魔法涉及其中,子进程确实没有从其父进程获取任何信息,除了参数和环境向量。只是 Unix 平台有这些约定,所以子进程知道它要使用的相关 fds,而父进程知道要为 fds 选择哪些数字。
对于需要传递两个或三个以上 fds 的进程,父进程确实必须显式传递编号。以下是我机器上一些明显发生这种情况的进程(在其他地方可能被塞进环境变量中):
klauncher --fd=8
/bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session