進程間通訊

1.無名管道

定義linux

           無名管道是一種特殊類型的文件,在內核空間中對應的資源便是一段內存空間,內核在這段空間以循環對列的方式臨時存入一個進程發送給另外一個進程的信息,這段內核空間徹底由操做系統管理和維護,應用程序只須要,也只能經過系統調用來訪它。編程

無名管道和普通的文件有很大的差別:數據結構

  • 無名管道的內核資源在通訊兩進程退出後會自動釋放。跟普通文件不一樣。
  • 存儲大量常規信息,可是編程方式,具備和普通文件同樣的特色,可使用read/write等函數進行讀寫操做,只是注意:特殊的文件只能用文件IO操做
  •  讀寫的特色有必定的差別,另外,不能用lseek函數來修改當前的讀寫位置,由於FIFO須要知足FIFO的原則。

特色:異步

  1. 使用條件:只能用於具備親緣關係(父子進程,兄弟進程等)的進程之間的通訊
  2. 通訊模式:半雙工模式,fd[0]做爲讀端fd[1]做爲寫端
  3. 讀寫方式:對於它的讀寫採用文件IO不支持lseek函數)
  4. 讀操做會阻塞(等待):在管道中無數據狀況下。寫操做會阻塞(等待):當管道被寫滿時,無名管道的大小爲64K
  5. 管道破裂:管道讀端關閉,再向管道中寫數據時,即向管道中寫入數據的進程將收到內核傳來的SIGPIPE信號。

函數接口:函數

/*
 * 函數的功能:在內核空間建立一個無名管道        
 * 參數:pipefd 固定的讀寫端 pipefd[0]---無名管道讀端,
 *                        pipefd[1]---寫端
 * 返回值:成功返回0,失敗-1
 */

#include <unistd.h>
int pipe(int pipefd[2]);

無名管道的4種特殊形式:ui

  1. 阻塞的方式讀無名管道:spa

    若是當前沒有進程(包括當前進程)訪問寫端讀操做當即返回,管道中無數據:當即返回0操作系統

    注意:若是寫端關閉,而且管道中實現沒有數據的話,讀端沒有任何意義。code

  2. 以阻塞的方式讀無名管道,若是某個進程(包括當前進程)能夠訪問寫端,管道端阻塞(等待)接口

    注意:讀寫端打開,當前管道中沒有數據,阻塞等待。

  3. 若是以阻塞的方式寫無名管道,若是沒有某個進程(包括當前進程)能夠訪問讀端,寫操做會收到SIGPIPE信號,write函數返回-1,若是當前有某進程能夠訪問讀端,且管道中有空間,則寫入成功。

  4. 若是以阻塞的方式寫無名管道,若是當前管道已經滿,則阻塞等待當前進程,若是有多個進程試圖寫,當進程讀管道喚醒寫操做時 ,喚醒哪一個進程未知,須要多個進程同時寫入時,須要相應的避免競爭機制。

    注意:無名管道只有全部進程都結束的時候,管道內的資源才徹底釋放,不然一直存在
     

2.有名管道

 定義:有名管道:有本身的名字,可是有名管道名稱保存在磁盤上,可是內容保存在內核中,有名管道和普通的文件同樣具備磁盤存放路徑,文件的權限和其餘的屬性信息,可是有名管道和普通文件又有區別,有名管道沒有在磁盤上存真正的信息,而是在內存中存放,2個進程結束後自動丟失,通訊結束後有名管道的文件路徑自己存在,這是和無名管道區別的地方。

特色:

  1. 有名管道可使互不相關的兩個進程互相通訊。
  2. 有名管道能夠經過路徑名來指出,而且在文件系統中可見。
  3. 讀寫方式:對於它的讀寫採用文件IO(不支持lseek函數)
  4. 其它與無名管道同樣
  5. 有名管道讀端寫端不固定。一段讀,另外一端寫。固然某一端既能夠讀也能夠寫,要用父子進程實現。

函數接口:

/*
 * 函數的功能:建立一個有名管道
 * 參數:pathname 有名管道的路徑加名稱
 *      mode 打開權限 0664
 *      mode & ~umask
 * 返回值:成功返回0,失敗-1
 */
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);

有名管道的4種特殊形式:

  1. 若是但願以寫的方式打開管道,則須要另外一進程以讀的方式打開管道。即若是以某種方式打開有名管道,則系統將阻塞進程,直到另外一個進程(包括本身)以另外一種方式打開該管道後纔會繼續運行,顯然一個進程能夠經過可讀可寫的方式打開管道,當前進程充滿了讀寫2個身份,此時進程入會阻塞。
  2. 兩進程已經徹底打開管道,阻塞讀操做,無數據,阻塞讀,有數據,讀出來
  3. 兩進程已經完成打開管道的操做,阻塞寫操做,管道中沒空間,阻塞,有空間寫入,寫滿阻塞。
  4. 兩進程已經徹底打開管道操做,中途其中一個進程退出,未退出一端是寫操做,將返回SIGPIPE信號,未退出一端是讀操做,讀操做將再也不阻塞,直接返回0(父子進程)

3.信號---進程間惟一的一種異步通訊方式

函數接口:

/*
 * 函數的功能:向執行的進程發送信號
 * 參數:pid 執行的進程號
 *      pid <-1 發送當前的進程|id|等於調用進程組id下的任意一個子進程
 *      pid=-1 發送給全部的進程,除了init(1號進程)
 *      pid =0 發送給同組下的全部進程
 *      pid >0 發送給指定的進程
 *      sig 指定的信號(kill -l)
 * 返回值:成功返回0,失敗-1;
 */
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

        

4. 消息隊列

  消息對列是消息的鏈式隊列,消息隊列的FIFO原則僅僅適用於同類型的消息,在消息隊列進行以下規定,不一樣系統的限制值能夠經過msgctl函數使用IPC_INFO參數得到,注意不一樣的linux版本此值不一樣。消息隊列即知足的管道的先進先出的原則,用戶又能夠按照指定的消息類型去存取,消息隊列存在於內存當中,在使用消息隊列的時候,經過指定消息對列的標識符。默認的狀況下:整個系統最多容許有16個消息隊列。每一個消息對列最大爲16384字節 消息對列中每一個消息最大爲8192字節。
消息對列的使用步驟:

  1. ftok----使外部不相關的進程創建聯繫
  2. msgget---建立一個消息隊列
  3. msgctl---刪除消息隊列
  4. msgsnd--發送消息
  5. msgrcv----接收消息

5. 共享內存-----進程間最高效的通訊方式

定義:共享內存進程間通訊機制主要用於實現進程間的大量數據的傳輸。共享內存是在內存中單獨開闢的一段內存空間,這段內存空間有本身特有的數據結構,包括訪問權限大小最近的訪問的時間。

兩個進程在使用此共享內存空間以前,須要在進程地址空間和共享內存空間之間創建聯繫,即將共享內存空間掛載到進程中。在使用共享內存進行數據存取時,有必要使用二元信號量來同步兩個進程以實現對共享內存的寫操做。

/*
 * 函數的功能:建立或者打開一個共享內存
 * 參數:key 外部鍵值
 * size 設置共享內存大小
 * shmflg 標誌位 IPC_CRAT   (flag)
                IPC_EXCL    0664
 * 返回值:成功返回共享內存的標識符  失敗:-1
 */
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);

/*
 * 函數的功能:將共享內存映射到各自進程空間
 * 參數:shmid 進程標識符
 * shmaddr 映射後進程的地址
 * shmflg 0 可讀可寫
 * SHM_RDONLY 只讀
 * 返回值:成功返回映射後地址,失敗NULL===(void *)-1
 */
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);

/*
 * 函數的功能:解除映射
 * 參數:shmaddr 映射的地址
 * 返回值:成功返回0,失敗-1       
 */
int shmdt(const void *shmaddr);

/* 
 * 函數的功能:刪除共享內存
 * 參數:shmid 共享內存的標識符
 * cmd IPC_STAT :獲得共享內存的狀態,把共享內存的shmid_ds結構複製到buf中.
 * IPC_SET :改變共享內存的狀態,把buf所指的shmid_ds結構中的uid、gid、mode複製到共享內存的shmid_ds結構內.
 * IPC_RMID :刪除這片共享內存。
 * buf 共享內存的屬性信息 NULL
 * 返回值:IPC_RMID 成功返回0,失敗-1
*/
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
 

6.信號燈集----同步互斥機制

相關文章
相關標籤/搜索