mirror of
https://github.com/duguosheng/6.S081-All-in-one.git
synced 2026-05-11 00:49:27 +08:00
更新文章
This commit is contained in:
@@ -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可以创建一个进程树。这个树的叶子是命令,内部节点是等待左右两个子进程完成的进程。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user