一.基本概念
進程間通訊:進程之間交換數據的過程叫進程間通訊。
進程間通訊的方式:、
簡單的進程間通訊:
命令行:父進程經過exec函數建立子進程時能夠附加一些數據
環境變量表:父進程經過exec函數建立子進程順便傳遞一張環境變量表
信號:父子進程之間能夠根據進程號相互發送信號,進程簡單通訊
文件:一個進程向文件中寫入數據,另外一個進程從文件中讀取出來。
命令行,環境變量只能單向傳遞,信號太過於簡單,文件通訊不能實時。
XSI通訊方式:X/open 計算機制造商組織。
共享內存,消息隊列,信號量,
網絡進程間通訊方式:
網絡通訊就是不一樣機器的進程間通訊方式
傳統的進程間通訊方式:管道
二.管道
1.管道是一種古老的通訊方式(基本上再也不使用)
2.早期的管道是一種半雙工,如今大多數是全雙工的
3.有名管道(管道是以文件的方式存在的)
建立管道文件:
命令mkfifo
函數mkfifo
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
管道通訊的編程模式:
進程A 進程B
建立管道mkfifo
打開管道文件open 打開管道
寫/讀數據write/read 讀/寫數據
關閉管道close 關閉管道
4.無名管道:由內核幫助建立,只返回管道的文件描述符,看不到管道文件,這種管道只能用於fork建立的父子進程之間
int pipe(int pipefd[2]);
pipefd[0]用來讀數據
pipefd[1]用來寫數據
練習:使用無名管道讓父子進程通訊
三.XSI IPC進程間通訊
1.XSI通訊是依靠內核的IPC對象進程通訊
2.每個IPC對象都有一個IPC標識(相似文件描述符),IPC標識符是一個非負整數。
3.IPC對象必需要先建立,建立後才能進程獲取,設置,操做,刪除。
4.建立IPC對象必需要提供一個鍵值(key_t),鍵值是建立獲取IPC對象的依據
5.產生鍵值的方法:
固定的字面值:1980014
使用函數計算:ftok(項目路徑,項目id)
使用宏讓操做系統隨機分配:IPC_PRIVTE
必須把獲取到的IPC對象標識符記錄下來,告訴其餘進程
6.XSI能夠建立的IPC對象有:
共享內存,消息隊列,信號量
四.共享內存
1.由內核維護一塊共享的內存區域,其餘進程把本身的虛擬地址映射到這塊內存,而後多個進程之間共享這塊內存了。
2.這種進程間通訊的好處是不須要信息複製
,它是進程間通訊最快的一種方式。
3
.這種方式會面臨同步的問題,須要與其餘的通訊方式配合,最合適的方式就是信號。
共享內存的編程模式:
1.進程之間要約定一個鍵值
進程A 進程B
建立共享內存
加載共享內存 加載共享內存
卸載共享內存 卸載共享內存
銷燬共享內存
int shmget(key_t key, size_t size, int shmflg);
功能:建立共享內存
size:大小
模式:
返回值:IPC對象標識符(相似於文件描述符)
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:加載共享內存()
shmid:shmget的返回值
shmaddr:進程提供的虛擬地址,也能夠爲NULL,若是爲空,操做系統會自動選擇一塊地址映射
shmflg:
SHM_RDONLY:映射內存的權限爲只讀
SHM_REMAP:映射已經存在的內存共享
SHM_RND:當shmaddr爲空時自動分配
mode_flag:權限
int shmdt(const void *shmaddr);
功能:這個地址對應的共享內存取消映射關係
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:控制/銷燬共享內存
cmd:
IPC_STAT:獲取共享內存的屬性
IPC_SET:設置共享內存的屬性
IPC_RMID:刪除共享內存
buf:
記錄共享內存屬性的對象
五.消息隊列
1.
消息隊列是一個由系統內核負責存儲和管理,並經過IPC對象標識符獲取的數據鏈表
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
msgflg:
建立IPC_CREAT | IPC_EXCL
獲取:0
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息隊列發送消息
msqid:msgget的返回值
msgp:消息(消息類型+消息內容)的首地址
msgsz:消息內容的長度(不包含消息類型)
msgflg:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
功能:從消息隊列接收消息
msgp:存儲消息的緩衝區
msgsz:要接收的消息長度
msgtyp:要接收消息的類型,(包含在消息的前四個字節)
msgflg:
MSG_NOERROR:當消息的實際長度大於msgsz,則按照msgsz長度截取再發送,不然產生錯a
MSG_NOWAIT:若是想要接收的消息不存在,則直接返回。
不然阻塞等待。
MSG_EXCEPT:從消息隊列中接收第一個不是msgtype類型的第一個消息
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:控制/銷燬消息隊列
cmd:
IPC_STAT:獲取消息隊列的屬性
IPC_SET:設置消息隊列的屬性
IPC_RMID:刪除消息隊列
六.IPC相關命令:
ipcs -m 查看共享內存
ipcrm -m id 刪除共享內存
ipcs -q 查看消息隊列
ipcrm -q id 刪除消息隊列
七.信號量
信號量(信號燈),能夠看成進程與進程之間共享的全局變量,通常用來爲共享的資源計數。
信號量的使用方法:
1.進程A,建立信號量,並設置信號量的初始值(設置資源數)
2.進程B,獲取信號量,查看信號量(查詢剩餘資源的數量),減小信號量(使用資源),增長信號量(資源使用完畢歸還)
3.當一個進程減小信號量時,若是不能減(資源使用完畢),則進程能夠進入等待狀態,當信號量可以被減的時候(其餘進程把資源還回來了),進程會被喚醒
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
功能:建立獲取獲取信號量
nsems:信號量的數量
semflg:
IPC_CREAT
IPC_EXCL
0644之類的權限碼
int semop(int semid, struct sembuf *sops, unsigned nsops);
功能:對信號量增長或減小
struct sembuf {
unsigned short sem_num;
short sem_op;
short sem_flg; // IPC_NOWAIT標識不阻塞
}
int semctl(int semid, int semnum, int cmd, ...);
功能:對信號量的控制或釋放
semnum:信號量的編號
cmd:
IPC_SET 設置信號量的屬性
IPC_STAT 設置信號量的屬性
IPC_RMID 刪除信號量
IPC_INFO 獲取信號量的信息