更新文章

This commit is contained in:
duguosheng
2022-04-24 17:58:50 +08:00
parent b310c45323
commit 981ee233e3

View File

@@ -25,7 +25,7 @@ if (fork() == 0) {
程序调用`pipe`创建一个新的管道并在数组p中记录读写文件描述符。在`fork`之后,父子进程都有指向管道的文件描述符。子进程调用`close``dup`使文件描述符0指向管道的读取端前面说过优先分配最小的未使用的描述符然后关闭p中所存的文件描述符并调用`exec`运行`wc`。当`wc`从它的标准输入读取时,就是从管道读取。父进程关闭管道的读取端,写入管道,然后关闭写入端。
如果没有可用的数据,则管道上的`read`操作等待写入数据或关闭所有指向写入端的文件描述符,在后一种情况下,`read`将返回0就像到达数据文件的末尾一样。事实上`read`在新数据不可能到达前会一直阻塞,这是子进程在执行上面的`wc`之前关闭管道的写入端非常重要的一个原因如果wc的文件描述符之一指向管道的写入端wc将永远看不到文件的结束。
如果没有可用的数据,则管道上的`read`操作将会进入等待,直到有新数据写入或所有指向写入端的文件描述符都被关闭,在后一种情况下,`read`将返回0就像到达数据文件的末尾一样。事实上`read`在新数据不可能到达前会一直阻塞,这是子进程在执行上面的`wc`之前关闭管道的写入端非常重要的一个原因如果wc的文件描述符之一指向管道的写入端wc将永远看不到文件的结束。
Xv6 shell以类似于上面代码(***user/sh.c***:100)的方式实现了诸如`grep fork sh.c | wc -l`之类的管道。子进程创建一个管道将管道的左端和右端连接起来。然后对管道的左端调用`fork``runcmd`,对管道的右端调用`fork``runcmd`,并等待两者都完成。管道的右端可能是一个命令,该命令本身包含一个管道(例如,`a | b | c`),该管道本身`fork`为两个新的子进程(一个用于b一个用于c)。因此shell可以创建一个进程树。这个树的叶子是命令内部节点是等待左右两个子进程完成的进程。