打字猴:1.700436201e+09
1700436201 UNIX传奇:历史与回忆 [:1700434692]
1700436202 UNIX传奇:历史与回忆 4.4 管道
1700436203
1700436204 管道也许是Unix中最引人注目的创新。管道是一种机制,由操作系统提供,并通过shell轻松访问。它将程序的输出与另一程序的输入连接起来。操作系统让它发挥作用,只需要一个既简单又自然的shell符号就能用起来,结果是得到一种设计和使用程序的新思路。
1700436205
1700436206 将程序连接起来的想法由来已久。Unix语境中最清晰的陈述之一出现在道格·麦基尔罗伊在1964年写的一份内部文件里。这份文件提出,“像花园水管那样”把程序接在一起。图4-1的第一幅图来自我在贝尔实验室的办公室墙上挂了30年的陈旧纸页。其中有打字错误,打印质量也糟糕,这正好展示了打字文件通常是什么样子。第二幅图是更正后的抄本。
1700436207
1700436208
1700436209
1700436210
1700436211
1700436212
1700436213
1700436214 图4-1 道格·麦基尔罗伊关于管道的想法(1964年) [5]
1700436215
1700436216 道格原本想让程序与程序能够随意连接,但如何自然地描述一个无约束图并不那么容易,而且还存在语义上的问题:在程序之间流动的数据必须正确排队,而程序的无管理连接有可能容纳不了那么长的队列。而且肯无论如何也想不出实际应用场景。
1700436217
1700436218 但道格继续唠叨,肯继续思考。正如肯所说:“有一天,我想到了:管道。本质上就是管道。”他只花了一小时就在操作系统中添加了管道系统调用。他形容管道是“超级小菜”,因为I/O重定向的机制早已存在了。
1700436219
1700436220 肯将管道机制添加到shell,尝试使用。他说,结果“很震撼”。
1700436221
1700436222 管道符号是两个命令之间的一道竖杠,简单而优雅。例如,要计算某个目录中的文件数量,可以将ls的输出(每个文件一行)用管道导向wc(计算行数)的输入。
1700436223
1700436224 $ ls | wc
1700436225
1700436226
1700436227
1700436228
1700436229
1700436230 不妨将程序看成一种过滤器,读取数据进来,以某种方式进行处理,然后输出结果。有时这样做非常自然,例如在程序中选择、改变或计数。但有时过滤器并不是一边读入一边输出,例如,sort命令在产生任何输出之前必须读完所有输入。但这无关紧要——把它打包成可以放入管道中的过滤器,仍然有其意义。
1700436231
1700436232 肯和丹尼斯仅用一晚时间就升级了系统中的每个命令。最大的改变是,在未输入文件名参数时,从标准输入流中读取数据。标准错误流stderr的创造也有其必要性。标准错误是独立的输出流:发送给它的错误信息被区隔在标准输出之外,因此不会进入管道。总的来说,这事不难——大多数程序只需要抛弃会扰乱管道的无关信息,并将错误报告发送到stderr即可。
1700436233
1700436234 管道带动了很多令我记忆深刻的创新。管道面世的确切日期没人记得,不过应该是在1972年下半年,因为它没有出现在手册的第2版(1972年6月),但在第3版(1973年2月)中出现了。
1700436235
1700436236 关于如何组合既有程序而不是写新程序来完成某项任务,Unix房间的每位成员都有好主意。我的点子是深挖who命令。who命令列出当前登录的所有用户。在大多数人都在自己的计算机上工作的今天,who这样的命令意义并不大,但由于分时的本质是多人共享同一台计算机,所以知道还有谁也在使用系统会很有帮助。who命令确实增加了社群感:你可以看到谁登录了系统。遇到问题时,即使大家都是深夜在家工作,也可以寻求对方帮助。
1700436237
1700436238 who命令为每个登录用户输出一行信息,grep查找符合特定模式的所有文本,wc统计行数,所以使用以下管道就能获知登录用户的状态。
1700436239
1700436240     who                     # 谁登录了?    who | wc                # 有多少人登录了?    who | grep joe          # 乔登录了吗?    who | grep joe | wc     # 乔登录过多少次?
1700436241
1700436242
1700436243
1700436244
1700436245
1700436246 要想了解管道提供了怎样的改进,请考虑在没有管道的情况下,使用I/O重定向到文件,最后一个任务(乔登录过多少次)将如何执行:
1700436247
1700436248     who >temp1    grep joe temp2    wc
1700436249
1700436250
[ 上一页 ]  [ :1.700436201e+09 ]  [ 下一页 ]