我的外部記憶區

2006年5月8日星期一

Unix痛恨者手冊2:第六章:管道

Unix受虐狂們,歡迎來到Unix下水道。

「在我們這個世紀,巴黎下水道仍是一個神秘的場所。如果知道自己的下面是個可怕的大窖,巴黎會感到不安。」 —— 雨果 《悲慘世界》

下面只是我自己對Unix的看法。大約六年前(當我有了第一台工作站的時候),我用了很多時間學習Unix。應該學得算是不錯的。幸運的是,腦子裡的這些垃圾正隨著時間的推移慢慢降解。可是,自從這個討論開始以來,不少Unix支持者發給我例子來「證明」Unix的強大。這些例子當然喚起了我許多美好的回憶:他們都是用一種最怪異的方式去實現一些簡單而無用的功能。

有個傢伙發了篇貼子講述一個shell腳本是如何讓他獲得「圓滿」的(這個腳本使用了四個噪聲一樣的命令把他所有的'.pas'後綴的文件改名為'.p'文件)。可我還是想把自己的宗教熱情留給比改幾個文件名更重要的事情上。是的,這就是Unix工具留給我的記憶:你用大量的時間去學那些複雜奇特的花架子,可到頭來卻是一場空。我還是去學些有用的真功夫吧。

——Jim Giles Los Alamos國家實驗室

Unix迷們拜倒在管道(pipe)的真善美之下。他們他們歌唱管道:沒有管道就沒有Unix。他們異口同聲地頌揚管道:「管道能夠讓你用簡單的程序去構造更複雜的程序。管道能夠以意想不到的方式去使用命令,管道使得實現更為簡單。」不幸的是,頌歌對Unix的作用並不比對偉大旗手的要好多少。

管道並不是一無是處。模塊化和抽像化是建立複雜系統中所必需的,這是計算機科學的基本原則。基本工具越是優秀,用其建立的複雜系統就會更為成功,可維護性也越高。管道作為構造工具還是有價值的。

以下是個管道的例子:

egrep '^To:|^Cc:' /var/spool/mail/$USER | \  cut -c5- | \  awk '{ for (i = 1; i <= NF; i++) print $i}' | \  sed 's/,//g' | grep -v $USER | sort | uniq 

看明白了麼?這個程序通過讀取用戶的郵箱,得到用戶所在的郵件列表(差不多是這個意思)。和你家裡的水管一樣,這個Unix管道也會在特定情況下神秘地破裂。

管道有時的確很有用,但它通過連接標準輸入輸出的方式進行進程間通訊,這個機制限制了它的應用。首先,信息只能單向流動。進程無法通過管道進行雙向通訊。其次,管道不支持任何形式的抽像。發送方和接收方只能使用字符流傳輸信息。比字符稍微複雜一點的對象是不能通過管道直接傳輸的,必須串行化為字符流以後才成,當然接收方必須對得到的字符流進行重新組裝。這意味著你無法傳輸一個對像以及用於建立這個對象的定義代碼。你無法傳輸指針到另一個進程的地址空間。你無法傳輸文件句柄或socket句柄或文件權限屬性。

冒著被罵做自以為是的風險,我們認為正確的模型應該是過程調用(本地的或是遠程的),用以傳遞第一類結構(first-class structures)(這是C語言從一開始就支持的)和函數組合(functional composition)。

管道對簡單任務是不錯的,比如文本流處理,但用它來建立健壯軟件就顯得有些捉襟見肘了。例如,早期關於管道的一篇論文中說明了如何使用管道把一些小程序組合在一起來構成一個拼寫檢查程序。這是體現簡單性的經典之作,但如果真的用來檢查拼寫錯誤就再糟糕沒有了。

管道在shell腳本中有經常能露一小手。程序員用它實現一些簡單而脆弱的解決方案。這是因為管道使得兩個程序之間產生了倚賴關係,如果你修改了一個程序的輸出格式,就必須同時修改另一個程序的輸入處理。

大多數程序是一步步建立起來的:首先制定程序的需求規範,然後程序的內部逐漸成型,最後寫一個輸出處理函數。管道則不把這一套放在眼裡:只要有人把一個半生不熟的程序放到了管道中,其輸出格式就定死了,不管是多麼不一致,不標準和低效,你都只能認命了。

管道不是程序間通訊的唯一選擇。Macintosh就沒有管道,我們最喜歡的Unix宣傳手冊是這樣寫的:

但是,Macintosh採用的則是截然相反的一種模型。系統不和字符流打交道。數據文件具有更高的層次,總是和特定的程序相關的。你什麼時候把一個Mac程序的輸出傳給另一個過?(如果能找到管道符都算你運氣)程序自成一體,你必須徹底明白自己在幹嘛呢。你無法把MacFoo和MacBar搞到一起。-— 摘自 《Unix生活》 Libes和ressler著

是呀,這些可憐的Mac用戶。如果無法把字符流通過管道四處亂傳,他們怎麼能在文檔中插入繪畫程序製作的圖片?怎麼能插入一個表格文檔?怎麼能把這個東拼西湊成的用電子郵件發出去?接到以後又怎麼能無縫地對它進行瀏覽和編輯,再回復回去?沒有管道,我們不能想像這一切在過去的十年中是如何被Macintosh做到的。

上次你的Unix工作站和Macintosh一樣有用是什麼時候?上次你能在它上面跑不同公司(甚至是同一公司的不同部門)的軟件是什麼時候?更不用說這些軟件能互相通信。如果Unix真做到了這一點,那是因為Mac軟件開發商拼了老命把他們的軟件移植到了Unix上,寄希望於讓Unix看起來像Mac一些。

Unix和Macintosh操作系統的根本區別是,Unix是為取悅程序員而設計的,而Mac是為了取悅用戶。(Windows一門心思想取悅的則是會計,不過這有些跑題了)。

研究表明管道和重定向是難於使用的,不是因為想法本身,而是由於其隨意和不直觀的限制。Unix自己的文檔早就指明了只有Unix死黨才能體會管道的妙處。

日期: thu, 31 Jan 91 14:29:42 EST 發信人: Jim Davis  收信人: UNIX-HATERS 主題: Expertise (專業知識)  今天早上我讀到《人機接口雜誌》上的一篇文章《計算機操作系統專業知識》,是Stephanie  M. Doane和其他兩位作者寫的。猜猜他們研究的是什麼操作系統?Doane對Unix新手、中手和專家的知識和表現進行了研究,下面是一些摘要:  「只有專家能夠使用Unix特有的一些功能(例如管道和重定向)來構造命令組合」  換句話說,Unix的每個新功能(除了那些從其他系統上生搬硬套過來的)都是如此怪異,以至於必須經過多年同樣怪異的學習和實踐才能掌握。  「這個發現有些出乎意料,因為這些正是Unix的基礎功能,而且這些功能是所有初級課程都會涉及的」  她還引用了S. W. Draper的一些文章,Draper相信:  「世上根本沒有什麼Unix專家,如果專家指的是這樣一些人,他們窮盡了某專業的所有知識,無需再學習什麼了。」  這一點我不能苟同。在學習Unix各種荒謬技術的征途上,已經有無數人被「窮盡」了。  

有些程序甚至吃飽了撐的,把管道和文件重定向區別對待了:

發信人: Leigh L. Klotz  收信人: UNIX-HATERS 主題: | vs. < (|對<) 日期: Thu, 8 Oct 1992 11:37:14 PDT  collard% xtpanel -file xtpanel.out < .login unmatched braces unmatched braces unmatched braces 3 unmatched right braces present  collard% cat .login | xtpanel -file xtpanel.out collard%  你自己琢磨琢磨吧。

沒有留言: