C++ shell如何通过管道传递子进程?

C++ shell如何通过管道传递子进程?,c++,c,linux,unix,linux-kernel,C++,C,Linux,Unix,Linux Kernel,最近我在学习linux进程间通信。但我在理解管道机制方面有一些问题 我知道管道是由父进程创建的一对文件,然后父进程将文件描述符传递给其子进程,然后子进程可以对其进行操作 但既然在fork()之后调用exec()时,子进程有一个全新的虚拟内存,那么为什么父进程可以将其信息传递给子进程呢?有什么我遗漏的吗?文件描述符是操作系统(内核)管理的资源的句柄。当您创建管道时,内核将创建设施,以便数据可以从管道的一端发送到另一端 此数据通过内核发送 当您使用fork()时,子级继承所有文件描述符,这意味着它们

最近我在学习linux进程间通信。但我在理解管道机制方面有一些问题

我知道管道是由父进程创建的一对文件,然后父进程将文件描述符传递给其子进程,然后子进程可以对其进行操作


但既然在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--会话

文件描述符指向内核中的公共文件数据结构,因此内核可以将同一文件公开给多个进程。请访问www.aosabook.org(bash)和Jessi Storimer()。不知道这是否会回答您的问题,但会给您一些见解。由内核管理的资源称为文件描述。From:open()函数应在文件和文件描述符之间建立连接。应创建引用文件的打开文件描述和引用该打开文件描述的文件描述符。其他I/O函数使用文件描述符来引用该文件。