Linux程式間通訊1

mf1crystal發表於2017-12-07

程式間通訊概述
目的:
1.資料傳輸
一個程式需要將它的資料傳送給另一個程式
2.資源共享
多個程式之間共享同樣的資源
3.通知事件
一個程式需要向另一個或一組程式傳送訊息,通知它們發生了某種事件
4.程式控制
有些程式希望完全控制另一個程式的執行(如Debug程式),此時控制程式希望能夠攔截另一個程式的所有操作,並能夠及時知道它的狀態改變
發展
Linux程式間通訊(IPC)由以下幾部分發展而來:
1.UNIX程式間通訊
2.基於System V程式間通訊
3.POSIX程式間通訊
POSIX
POSIX(Portable Operating System Interface)表示可移植作業系統介面。
電氣和電子工程師協會(IEEE)最初開發 POSIX 標準,是為了提高 UNIX 環境下應用程式的可移植性。然而,POSIX 並不侷限於 UNIX,許多其它的作業系統,例如 DEC OpenVMS 和 Microsoft Windows,都支援 POSIX 標準
分類
現在Linux使用的程式間通訊方式包括:
1、管道(pipe)和有名管道(FIFO)
2、訊號(signal)
3、訊息佇列
4、共享記憶體
5、訊號量
6、套接字(socket)
管道通訊
管道是單向的、先進先出的,它把一個程式的輸出和另一個程式的輸入連線在一起。
一個程式(寫程式)在管道的尾部寫入資料,另一個程式(讀程式)從管道的頭部讀出資料
資料被一個程式讀出後,將被從管道中刪除,其它讀程式將不能再讀到這些資料。
管道提供了簡單的流控制機制,程式試圖讀空管道時,程式將阻塞。同樣,管道已經滿時,程式再試圖向管道寫入資料,程式將阻塞
侷限性
(1)管道實現的是半雙工通訊,即資料只能在一個方向上流動;
(2)只能在具有公共祖先的程式之間使用管道進行通訊。通常,由一個程式建立管道,然後呼叫fork建立子程式,隨後在父,子程式應用該管道進行通訊。

管道包括無名管道和有名管道兩種,前者用於父程式和子程式間的通訊,後者可用於執行於同一系統中的任意兩個程式間的通訊。
無名管道建立:
int pipe(int filedis[2]);
當一個管道建立時,它會建立兩個檔案描述符:
filedis[0] 用於讀管道,
filedis[1] 用於寫管道。
管道的讀寫
管道用於不同程式間通訊。通常先建立一個管道,再通過fork函式建立一個子程式,該子程式會繼承父程式所建立的管道
注意:必須在系統呼叫fork( )前呼叫pipe( ),否則子程式將不會繼承檔案描述符
命名管道FIFO
命名管道和無名管道基本相同,但也有不同點:
無名管道只能由父子程式使用;
但是通過命名管道,不相關的程式也能交換資料。
訊號通訊
訊號(signal)機制是Unix系統中最為古老的程式間通訊機制,很多條件可以產生一個訊號:
1、當使用者按某些按鍵時,產生訊號
2、硬體異常產生訊號:除數為0、無效的儲存訪問等等。這些情況通常由硬體檢測到,將其通知核心,然後核心產生適當的訊號通知程式,例如,核心對正訪問一個無效儲存區的程式產生一個SIGSEGV訊號
3、程式用kill函式將訊號傳送給另一個程式
4、使用者可用kill命令將訊號傳送給其他程式
訊號型別
下面是幾種常見的訊號:
§ SIGHUP: 從終端上發出的結束訊號
§ SIGINT: 來自鍵盤的中斷訊號(Ctrl-C)
§ SIGKILL:該訊號結束接收訊號的程式
§ SIGTERM:kill 命令發出的訊號
§ SIGCHLD:標識子程式停止或結束的訊號
§ SIGSTOP:來自鍵盤(Ctrl-Z)或除錯程式的停止執行訊號
訊號處理
當某訊號出現時,將按照下列三種方式中
的一種進行處理:
1、忽略此訊號
大多數訊號都按照這種方式進行處理,但有兩種訊號
決不能被忽略,它們是:
SIGKILL\SIGSTOP。
這兩種訊號不能被忽略的原因是:
它們向超級使用者提供了一種終止或停止程式的方法
2、執行使用者希望的動作
通知核心在某種訊號發生時,呼叫一個使用者函式。在使用者函式中,執行使用者希望的處理
3、執行系統預設動作
訊號傳送
Kill既可以向自身傳送訊號,也可以向其他程式傳送訊號。與kill函式不同的是,raise函式是向程式自身傳送訊號
kill的pid引數有四種不同的情況:
1、pid>0
將訊號傳送給程式ID為pid的程式。
2、pid == 0
將訊號傳送給同組的程式。
3、pid < 0
將訊號傳送給其程式組ID等於pid絕對值的程式。
4、pid ==-1
將訊號傳送給所有程式。
使用alarm函式可以設定一個時間值(鬧鐘時間),當所設定的時間到了時,產生SIGALRM訊號.如果不捕捉此訊號,則預設動作是終止該程式經過了指定的seconds秒後會產生訊號SIGALRM
每個程式只能有一個鬧鐘時間.如果在呼叫alarm時,以前已為該程式設定過鬧鐘時間,而且它還沒有超時,以前登記的鬧鐘時間則被新值代換
如果有以前登記的尚未超過的鬧鐘時間,而這次seconds值是0,則表示取消以前的鬧鐘
pause函式使呼叫程式掛起直至捕捉到一個訊號。

        int pause(void)

只有執行了一個訊號處理函式後,掛起才結束
當系統捕捉到某個訊號時,可以忽略該訊號或是使用指定的處理函式來處理該訊號,或者使用系統預設的方式
訊號處理的主要方法有兩種,
一種是使用簡單的signal函式,
另一種是使用訊號集函式組

相關文章