Linux進程間通信,大致有五種
原始的信號和管道,還有共享內存,消息隊列和信號。
1. 管道
管道分爲兩種 pipe和fifo
pipe可用有親緣關係的進程,比如父子進程,兄弟進程
fifo可用不同進程之間,不限於親緣關係
pipe
半雙工,一端讀一端寫,數據在一個方向上流動。可以看成是一種特殊的文件,只不過它只在內存裏,不落地到文件系統。
管道的緩衝區有限制,PIPE_BUF 一般是一個頁面的大小,管道傳輸的無格式字節流,這就要求讀寫雙發要實現約定好數據格式。它沒有名字,所以只能在親緣關係進程之間使用。
fifo
一種特殊文件,落地到文件系統。嚴格支持先進先出。
int mkfifo(const char * pathname, mode_t mode)
2. 信號
信號,一個進程向另一個進程發送很簡短的信號,通知某個事情。
信號在signal.h中有定義,SIG開頭的都是信號。
這裏要重點掌握兩個函數
- signal
- sigaction 專業
sigaction的優勢在於,在調用它之前,可以設置信號屏蔽字可以防止信號在它的處理函數還未運行結束時就被接收到的情況。
還有兩個發送信號的函數 - kill
- alarm
3. 共享內存
共享內存,可以允許兩個以上的進程同時訪問一個塊內存。這個內存實際上是在內核態中的,進程使用時,會映射到進程的地址空間中。
主要函數
- shmget 創建或者打開共享內存
int shmget(key_t key, size_t size, int shmflg); - shmat 把共享內存映射過來
void *shmat(int shm_id, const void *shm_addr, int shmflg); - 解除映射
int shmdt(const void *shmaddr); - 控制共享內存
int shmctl(int shm_id, int command, struct shmid_ds *buf);
命令選項
IPC_STAT 設置共享內存訪問權限
IPC_SET 設置共享內存訪問權限
IPC_RMID 刪除共享內存
4. 消息隊列
消息隊列,是消息的鏈表,存放再內核中,有一個標識符(隊列id)標記(其實就是ipc id, 這裏ipc指的是system v ipc ,其實共享內存和信號也都有這個id)。
寫權限的進程可以往消息隊列中添加消息
具有讀權限的進程可以從消息隊列中讀取信息。
又因爲它在內核中,所以多進程之間可以訪問,在進程結束時,消息隊列不會被清除。
可按照類型隨機查詢,並不一定要按先進先出的次序讀取。
消息: 定長消息頭+變長消息正文
- msgget//創建或者打開一個消息隊列
- msgsnd
- int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, long
mtype,
int msgflg )
mtype 如果mtype 的值是零的話,函數將不做類型檢查而自動返回隊列中的最早的消息 - msgctl //操作消息隊列
5. 信號量
信號量其實有點不同,是用來保持進程之間互斥和同步,而不是共享數據的。它提供一種訪問機制,讓一個臨界區只能由x個進程來訪問。它是一種特殊的變量,程序對其訪問都是原子操作,由兩種操作,一種時等待P,另一種時發送V
- P(sv): 當sv>0時,sv-1,向下執行;當sv=0時,掛起
- V(sv): 當系統由因爲等待sv而掛起的進程時,使其執行;如果沒有,sv+1
信號量三個函數
- semget 打開和創建一個信號量
- semop 信號量P V操作
- semctl 信號量初始化,刪除操作