shell如何对子进程进行管道处理
How does shell pipe the child process?
最近我在研究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], ...);
信息不会传递给子进程,而是通过隐式约定完成的。父级知道它应该将fds复制到插槽0,1,2中,子级知道从这些描述符中读取/写入。你说得对,exec中没有魔法,除了参数和环境向量之外,子代实际上从其父代获得的信息为零。只是unix平台有这些约定,所以子代知道它要使用的相关fds,而父代知道为fds选择哪些数字。
对于需要传递两个或三个以上fds的进程,父进程确实必须显式传递数字。以下是我的机器上明显发生这种情况的一些过程(它可能被填充在其他地方的环境变量中):
klauncher --fd=8
/bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
- 警告处理为错误这里有什么问题
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 使用流处理接收到的数据
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 基于多个条件处理地图中的所有元素
- 如何用数字处理log(0)
- IPC使用多个管道和分支进程来运行Python程序
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- 错误处理.将系统错误代码映射到泛型
- AMQP-CPP:TCP 处理程序中的管道损坏错误
- 用管道在C++中创建调度队列/线程处理程序:FIFO溢出
- Android上的零拷贝相机处理和渲染管道
- shell如何对子进程进行管道处理
- zeromq管道有多个工人,但有一个水槽,当工人到达呼吸机时,水槽可以处理订单中的工人输出
- Boost::range用于处理容器的内容,并将映射中的值管道到下一个进程
- 设计用于处理对象的管道