C++ shell如何通过管道传递子进程?
最近我在学习linux进程间通信。但我在理解管道机制方面有一些问题 我知道管道是由父进程创建的一对文件,然后父进程将文件描述符传递给其子进程,然后子进程可以对其进行操作C++ shell如何通过管道传递子进程?,c++,c,linux,unix,linux-kernel,C++,C,Linux,Unix,Linux Kernel,最近我在学习linux进程间通信。但我在理解管道机制方面有一些问题 我知道管道是由父进程创建的一对文件,然后父进程将文件描述符传递给其子进程,然后子进程可以对其进行操作 但既然在fork()之后调用exec()时,子进程有一个全新的虚拟内存,那么为什么父进程可以将其信息传递给子进程呢?有什么我遗漏的吗?文件描述符是操作系统(内核)管理的资源的句柄。当您创建管道时,内核将创建设施,以便数据可以从管道的一端发送到另一端 此数据通过内核发送 当您使用fork()时,子级继承所有文件描述符,这意味着它们
但既然在fork()之后调用exec()时,子进程有一个全新的虚拟内存,那么为什么父进程可以将其信息传递给子进程呢?有什么我遗漏的吗?文件描述符是操作系统(内核)管理的资源的句柄。当您创建管道时,内核将创建设施,以便数据可以从管道的一端发送到另一端 此数据通过内核发送 当您使用fork()时,子级继承所有文件描述符,这意味着它们继承由文件描述符所引用的内核管理的数据结构。 因此,现在文件描述符指的是子级和父级中完全相同的内核资源。由于内核资源位于内核中,这部分在两个进程之间共享,因此它不像用户空间内存那样重复 基本上,您将()数据写入管道的一端,该数据被复制到内核的缓冲区中。然后可以读取()该数据,并将其从内核缓冲区复制到读取过程的内存空间中。在fork()之后,子进程和父进程都引用内核中使用pipe()创建的同一缓冲区。当一个进程exec()转到另一个进程时,该子进程通常继承父进程的标准文件路径:stdin(0)、stdout(1)、stderr(2)。当shell创建管道时,它使用
dup2()
调用将路径复制到所需的路径号,以便强制将正确的路径复制到子级的标准路径
// 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], ...);
信息不会传递给子进程,而是通过隐式约定完成的。父级知道应该将FD复制到插槽0、1、2中,而子级知道如何从这些描述符读取/写入。你是对的,在整个exec中没有魔法,除了参数和环境向量之外,子对象确实从父对象那里获得了零信息。只是unix平台有这些约定,所以孩子知道要使用的相关FD,家长知道要为FD选择哪些数字 对于需要传递两个或三个以上FD的进程,父进程确实必须显式传递该数字。下面是我机器上的一些进程,这些进程显然正在发生(它可能被塞进了其他地方的环境变量中):
klauncher--fd=8
/bin/dbus守护进程--fork--打印pid 5--打印地址7--会话