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