UNIX文化,提倡的是一種簡潔,直觀,低復雜度的文化.
UNIX倡導多進程編程,而不是大家所熟悉的多線程編程.
由于進程有自己獨立的地址空間,因此多進程之間的協(xié)作與交互,通關操作系統(tǒng)提供的各種IPC方法實現(xiàn).
在討論IPC的那個章節(jié)里,提出了管道,信號,臨時文件,共享內(nèi)存,套接字幾個模型.
我一般寫東西玩的時候,總是喜歡建立控制臺程序,因為輸入輸出庫都比較簡單,并且所見即得.管道/重定向之類,都是建立在標準輸入/輸出的基礎上.這里所描述的管道/重定向,并不是在一個進程中調(diào)用CreatePipe,改變管道方向,然后用CreateProcess建立一個子進程.UNIX所用的方式類似于.bat命令,比如 dir | more,用符號"|"連接兩個進程的管道.事實上,一般能用上管道/重定向的進程,都是一個過濾器,數(shù)據(jù)從標準輸入進來,經(jīng)過加工后從標準輸出跑掉.因此,管道/重定向技術對于流水線般加工的任務,是一個相當棒的模型.
需要注意的是,使用管道模型的程序,通常數(shù)據(jù)流/協(xié)議(在某個任務下)是單向的.
總體上,在WINDOWS下像UNIX那樣使用管道/重定向機制,通常是用C/C++寫許多獨立但是可以連接的程序,然后用bat的方式,將其按所需任務組合.如果希望在程序中可以像bat那樣啟動其他進程,只要用簡單的system(command)函數(shù)就好了,WINAPI通常都是復雜而累贅的.
UNIX下的信號,是對進程發(fā)出的,由進程的相應回調(diào)函數(shù)處理,程序可以重載自己的實現(xiàn).這和WINDOWS下的消息比較相像,只是WM通常都需要窗口.由于信號/消息能傳遞的數(shù)據(jù)都比較薄弱簡單,所以這通常作為一種輔助機制,和其他IPC模型共同協(xié)作.
臨時文件,是一種能解決雙向溝通的模型,但是并不利于做復雜的事情,最好的用途是在簡單,需要雙方溝通,大數(shù)據(jù)量的情形下.使用方法大概描述為,A進程調(diào)用執(zhí)行某個任務的B進程,B進程將執(zhí)行結果寫入A進程指定的文件,A進程使用該文件.
一個隱患是,一旦破壞程序知道臨時文件的位置,就可能破壞該文件.
其實臨時文件和接下來所說的共享內(nèi)存在功能上并無太大區(qū)別.唯一不同的是,臨時文件所使用的API,都是很容易跨平臺的.
共享內(nèi)存,是一個和操作系統(tǒng)密切相關的IPC模型,作為生產(chǎn)者/消費者系統(tǒng)的一個性能優(yōu)化的解決方案,其最大的優(yōu)勢便是對大型數(shù)據(jù)傳遞所提供的效率.但是,預防競爭/死鎖是必須考慮的問題.我覺得,由于共享內(nèi)存的API通常是專有的,不易于跨平臺,所以使用共享內(nèi)存的條件應該比較嚴格,必須要在性能需求高和一次數(shù)據(jù)交換量巨大的情況下才可以考慮,而且,臨時文件是一個可以考慮的替代模型.
套接字,是一個直觀并且在眾多操作系統(tǒng)中廣泛使用的模型,不用說也知道是一個好東西了.
在《UNIX編程藝術》中,認為大多數(shù)的IPC方法都是可以相互替代的,因此最重要的是選擇一個盡可能使系統(tǒng)簡單的模型.此外,特別說多線程不該是最先考慮到的方法,而是最后一個.
多線程將子任務糅合在一個程序中,而不是分開,增加了全局復雜度.此外,多線程帶來的2個不可避免的BUG:時序問題,還有競爭/死鎖的問題.縱然全局變量提升了任務之間的溝通效率,但是通常這種效率都被昂貴的鎖定/解鎖所抵消了.
特別是,使用多線程的程序所依賴的庫,并非都是線程安全的,其中一旦產(chǎn)生的問題,會使得你麻煩重重,特別是,多線程的程序調(diào)試......由于時序問題,你自己想想都知道了.
因此,非要使用多線程,理想(意味著不可能存在)的約束是,線程盡量不使用全局變量;每個變量只被一個線程使用;被線程使用的變量不再被主進程使用;線程中不使用static變量.....這種約束,根本沒有辦法實現(xiàn)嘛.
posted on 2006-08-13 11:06
LOGOS 閱讀(2319)
評論(8) 編輯 收藏 引用 所屬分類:
《UNIX編程藝術》讀書筆記