歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> 關於Unix >> 進程間通信的方式---LinuxIPC小結

進程間通信的方式---LinuxIPC小結

日期:2017/3/6 15:47:58   编辑:關於Unix
現在最常用的進程間通信的方式有:信號,信號量,消息隊列,共享內存。 所謂進程通信,就是不同進程之間進行一些"接觸",這種接觸有簡單,也有復雜。機制不同,復雜度也不一樣。通信是一個廣義上的意義,不僅僅指傳遞一些massege。 他們的使用方法是基本相同
  現在最常用的進程間通信的方式有:信號,信號量,消息隊列,共享內存。
  
  所謂進程通信,就是不同進程之間進行一些"接觸",這種接觸有簡單,也有復雜。機制不同,復雜度也不一樣。通信是一個廣義上的意義,不僅僅指傳遞一些massege。
  
  他們的使用方法是基本相同的,所以只要掌握了一種的使用方法,然後記住其他的使用方法就可以了。
  
  1. 信號
  在我學習的內容中,主要接觸了信號來實現同步的機制,據說信號也可以用來做其它的事情,但是我還不知道做什麼。
  
  信號和信號量是不同的,他們雖然都可用來實現同步和互斥,但前者是使用信號處理器來進行的,後者是使用P,V操作來實現的。
  
  使用信號要先知道有哪些信號,在Linux下有31個需要記住的通用信號,據說也是systemV中最常用的那些。這裡略。
  
  1. 1信號相關函數:
  #include
  int sigaction(int signo, const struct sigaction *act, struct sigaction
  *oact);
  該函數用來為進程安裝信號處理器,struct sigaction數據是用來保存信號處理器的相關信息。
  
  #include
  int sigemptyset(sigset_t *set);
  將信號集合清空。
  int sigfillset(sigset_t *set);
  將信號集合設置成包含所有的信號。在對信號進行操作以前一定要對信號集進行初始化。
  
  int sigaddset(sigset_t *set, int signo);
  向信號集中加入signo對應的新信號。
  int sigdelset(sigset_t *set, int signo);
  從信號集中刪除signo對應的一個信號。
  int sigismember(const sigset_t *set, int signo);
  判斷某個信號是否在信號集中。返回1則在,0則不在。
  
  #include
  int sigprocmask(int how,const sigset_t *set, sigset_t *oset);用來設置進程的信號屏蔽碼。信號屏蔽碼可以用來在某段時間內阻塞一些信號集中的信號,如果信號不在信號集中,就不必討論它,因為肯定不響應,是否能生成也不肯定,我沒有做過試驗。
  
  1.2我所理解的使用信號機制的方法:
  使用信號,主要做的事情就是信號處理器的工作,這裡面是你想做的事情。就像中斷處理函數一樣。
  
  在使用信號以前,首先要初始化信號集,只有在信號集裡面的信號才會被考慮。
  
  有兩種方法可以初始化信號集,一種是設置空信號集,一種是將所有的信號都加到信號集中。如果你自己想要的信號集不是這兩種,可以在初始化了以後通過添加和刪除信號進行定制。
  
  如果在進程執行的一段時間內不想對某些信號進行響應,則可以使用sigprocmask對當前的信號集中的一些信號進行阻塞,稍後再執行。
  
  當你將信號集設置完畢後,在讓他工作之前需要安裝信號處理器。安裝信號處理器可以實現這幾個功能:
  
  指定信號處理函數的入口;指定信號屏蔽集合;指定信號處理器的一些標志。所謂信號處理器,就是指定了一些處理方法,關鍵在於安裝信號處理器,這是使正確的信號進行正確的處理關鍵。在安裝的時候,一定要對特定的信號賦予正確的信號處理函數。
  
  我不知道不同進程之間的信號處理器能否混用,但是像一個特定的進程中有多少個信號處理器這樣的問題是不能提的。因為信號處理器是一個概念,他針對的是信號,就是說如果你指定了一個數據結構,用它來存儲針對某個信號的處理信息,那麼安裝信號處理器就是賦予這個數據結構一些相關信息,使用信號處理器就是用這個數據結構存儲的信息來組織一種機制當發生這個信號的時候會做一些你實現設置好的處理。但是如果區分不同進程中對同一個信號的不同處理器?我想處理器可能只對核它所屬的進程有關的信號進行響應,但是如果是這樣的話,那這是怎麼實現的呢?
  
  不過有一點是可以知道的,那就是每一個信號都有一個信號處理器(確定的),可以動過安裝信號處理器來指定她的行為。信號處理器由他自己的信息存儲區域(我不知道在什麼地方),但是可以通過向sigaction類型的數據結構向信號處理器的信息存儲區域中傳遞信息。這個數據結構由一個就可以了,因為它只是臨時傳遞數據的載體。
  
  但是sigpromask和信號處理器裡面的sigmask是不一樣的,前者是在進程當前流程設置信號屏蔽,後者是指定在信號處理器作用時需要屏蔽掉的信號。例如,在設置某個特定信號的信號處理器時,我們當然不能讓它的信號處理器工作了,因為還沒有設置完嗎,這是我們可以使用sigprocmask來讓當前的流程開始阻塞該信號,當設置完信號處理器以後,再用sigprocmask恢復被阻塞的信號。而以後再接收到該信號時,信號處理器就可以工作了。
  
  我的想法是,同一個信號在不同的進程裡可以有不同的信號處理器(一般應該有一個缺省處理),當系統中發生一個信號時,所有能接受到的進程都可以接收到這個信號,並用他們自己的信號處理器對這個信號做出各自的響應。
  
  1.3如何用信號來進行進程間的同步
  同步的實現主要是通過在接受信號之前掛起進程,等待相關信號。所以涉及到異步信號安全函數的概念。
  
  不過信號如何來實現進程間的互斥,我理解不是很多,我想信號的主要用處還是在軟中斷處理和進程同步。
  
  2.信號量
  信號量和信號是不同的東西,仔細想想就可以理解:信號是實現約定的固定的值,而信號量是一個變量記錄著某些特定信息。
  
  信號量這種東西我們在操作系統課程中就已經接觸過了,這裡只是再草草說幾句。信號量分為有名和無名兩種。進程間通信用有名信號量,同一進程內部通信一般用無名信號量。這個我不再多說。
  2.1信號量相關函數
  #include
  #include
  #include
  int semget(key_t key, int nsems, int semflg);
  創建一個新的信號量組或獲取一個已經存在的信號量組。
  
  #include
  #include
  #include
  int semop(int semid, struct sembuf *sop, int nsops);
  semop函數可以一次對一個或多個信號量進行操作。
  Int semctl(int sem_id, int semnum, int cmd,/*union semun arg*/…);
  該函數可以用來獲取一些信號量的使用信息或者是來對信號量進行控制。
  
  2.2我對信號量機制的理解
  對信號量的操作只有兩個:P, V。為了在邏輯上便於組織信號量,信號量機制中有一個概念是信號量組。我們可以把一個信號量組中創建相關的信號量,這樣邏輯上清晰也便於管理。在使用之前你同樣需要對他們進行初始化:生成或打開信號量組,向其中生成或刪除你指定的信號量。
  
  對信號量的操作只用兩種,他都是通過semop函數中的sops參數來指定的,如果這個參數是一個數組的話,那麼就是對多個信號量進行操作。Sops參數中的sem_op字段指明了對信號量進行的是P操作還是V操作。你只要指定就行了,具體的操作不需要你去實現,函數中都已經提供了。使用信號量,你得清楚信號量組id和信號量在信號量組中的位置(其實也就是另一個id)。一個信號量必須屬於一個信號量組,否則不能被系統所使用。切記!信號量和信號量組是不會被系統所自動清理的,所以當你的進程退出前,千萬別忘了清理你生成的那些信號量們。
  
  信號量既可以實現互斥,也可以實現同步,這裡就不說了,操作系統課程中是有介紹的。
  
  3.消息隊列
  消息隊列是比較高級的一種進程間通信方法,因為它真的可以在進程間傳送massege,你傳送一個"I seek you"都可以。
  
  一個消息隊列可以被多個進程所共享(IPC就是在這個基礎上進行的);如果一個進程的消息太多一個消息隊列放不下,也可以用多於一個的消息隊列(不過可能管理會比較復雜)。共享消息隊列的進程所發送的消息中除了massege本身外還有一個標志,這個標志可以指明該消息將由哪個進程或者是哪類進程接受。每一個共享消息隊列的進程針對這個隊列也有自己的標志,可以用來聲明自己的身份。
  
  對於系統中的每一個消息隊列,都有一個數據結構來代表它,這個數據結構是msqid_ds,這裡略去不講,在中可以看到它的原型。
  
  3.1消息隊列相關函數
  使用消息隊列之前,你要麼獲得這個消息隊列,要麼自己建立一個,否則是不能使用消息隊列的(我覺得這都像是多余的話,請見諒)。當這個消息隊列不再使用時,也一定要有一個進程來刪除消息隊列,系統是不會自動的清理消息隊列和msgid_ds的。
  
  Int msgget(key_t key, int msgflg);獲取一個存在的消息隊列的ID,或者是根據跟定的權限創建一個消息隊列。但是怎麼樣去刪除這個消息隊列,我還不十分清楚。
  Int msgctl(int msqid, int cmd, struct msqid_ds *buf);用來從msqid_ds中獲取很多消息隊列本身的信息。
  Int msgsnd(int msqid, void *msgp, size_t msgsz, int msgflg);用於向隊列發送消息。
  Int msgrcv(int msqid, void *msgp, size_t msgsz, long int msgtyp, intmsgflg);
  從隊列中接收消息。
  我這個文檔裡面對消息隊列中的一些臨界情況所述不多,因為這是我的小結,而非介紹。在GNU C庫技術中可以看到它的詳細介紹。

Copyright © Linux教程網 All Rights Reserved