概念
進程間通信就是在不同進程之間傳播或交換信息,那么不同進程之間存在着什么雙方都可以訪問的介質呢?進程的用戶空間是互相獨立的,一般而言是不能互相訪問的,唯一的例外是 共享內存區 。但是,系統空間卻是“公共場所”,所以內核顯然可以提供這樣的條件。
除此以外,那就是雙方都可以訪問的 外設 了。在這個意義上,兩個進程當然也可以通過磁盤上的普通文件交換信息,或者通過“注冊表”或其它數據庫中的某些表項和記錄交換信息。廣義上這也是進程間通信的手段,但是一般都不把這算作“進程間通信”。因為那些通信手段的效率太低了,而人們對進程間通信的要求是要有一定的 實時性。
進程間通信主要包括: 管道,系統IPC ( 包括消息隊列,信號量,共享存儲 ),SOCKET.
管道包括三種
1) 普通管道 PIPE:通常有種限制,一是半雙工,只能單向傳輸;二是只能在父子進程間使用。
2) 流管道 s_pipe:去除了第一種限制,可以雙向傳輸。
3) 命名管道 name_pipe:去除了第二種限制,可以在許多並不相關的進程之間進行通訊。
系統IPC的三種方式類同,都是使用了內核里的標識符來識別
# 管道( pipe ):管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程間使用。進程的親緣關系通常是指父子進程關系。
# 有名管道 (named pipe) : 有名管道也是半雙工的通信方式,但是它允許無親緣關系進程間的通信。
# 信號量( semophore ) : 信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。 因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
# 消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩沖區 大小受限等缺點。
# 信號 ( sinal ) : 信號是一種比較復雜的通信方式,用於通知接收進程某個事件已經發生。
# 共享內存( shared memory ) :共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的 IPC 方式,它 是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號兩,配合使用,來實現進程間的同步和通信。
# 套接字( socket ) : 套解口也是一種進程間通信機制,與其他通信機制不同的是,它可用於不同及其間的進程通信。
常見問題
FAQ1: 管道與文件描述符,文件指針的關系?
答: 其實管道的使用方法與文件類似,都能使用read,write,open等普通IO函數. 管道描述符來類似於文件描述符. 事實上, 管道使用的描述符, 文件指針和文件描述符最終都會轉化成系統中SOCKET描述符. 都受到系統內核中SOCKET描述符的限制. 本質上LINUX內核源碼中管道是通過空文件來實現.
FAQ2: 管道的使用方法?
答: 主要有下面幾種方法: 1)pipe, 創建一個管道,返回2個管道描述符.通常用於父子進程之間通訊. 2)popen, pclose: 這種方式只返回一個管道描述符,常用於通信另一方是stdin or stdout; 3)mkpipe: 命名管道, 在許多進程之間進行交互.
FAQ3: 管道與系統IPC之間的優劣比較?
答: 管道: 優點是所有的UNIX實現都支持, 並且在最后一個訪問管道的進程終止后,管道就被完全刪除;缺陷是管道只允許單向傳輸或者用於父子進程之間.
系統IPC: 優點是功能強大,能在毫不相關進程之間進行通訊; 缺陷是關鍵字KEY_T使用了內核標識,占用了內核資源,而且只能被顯式刪除,而且不能使用SOCKET的一些機制,例如select,epoll等.
FAQ4: WINDOS進程間通信與LINUX進程間通信的關系?
答: 事實上,WINDOS的進程通信大部分移植於UNIX, WINDOS的剪貼板,文件映射等都可從UNIX進程通信的共享存儲中找到影子.
FAQ5: 進程間通信與線程間通信之間的關系?
答: 因為WINDOWS運行的實體是線程, 狹義上的進程間通信其實是指分屬於不同進程的線程之間的通訊.而單個進程之間的線程同步問題可歸並為一種特殊的進程通信.它要用到內核支持的系統調用來保持線程之間同步. 通常用到的一些線程同步方法包括:Event, Mutex, 信號量Semaphore, 臨界區資源等.