linux io 學習筆記(03)---共享內存,信號燈,消息隊列
system V IPC
1)消息隊列
2)共享內存
3)信號燈(信號量集)
1.消息隊列、
ipcs -q 查看系統中使用消息隊列的情況
ipcrm -q +msqid 刪除消息隊列
消息隊列工作原理:在內核空間上創建隊列,信息發送者將發送信息打包成結點添加到隊列中,信息的接受者選擇性從隊列上讀取想要的節點
1)創建隊列,2)向隊列中添加信息,3)從隊列中移除信息,4)實現隊列的控制(獲取隊列的屬性,設置隊列的屬性,刪除不使用的隊列)
1)創建隊列:
函數原型:key_t ftok(const char *pathname,int proj_id);
功能 :生成key值
參數 :pathname 路徑名(用戶給定,路徑必須真實存在)
proj_id 傳字符
返回值:成功 key值 隨機數
失敗:-1
函數原型:intmsgget(key_t key,int msgflg);
功能: 創建消息隊列
參數: key 值 0或非0 key值確保消息隊列的唯一性
msgflg 標誌位 IPC_CREAT|IPC_EXCL|0664 創建並打開消息隊列(如果消息隊列不存在,自動創建,如果存在,返回EEXIST)
0664 按該權限打開消息隊列。
返回值:成功: 消息隊列標識符
失敗 -1
2)添加消息
函數原型:int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);
功能 :將消息添加到隊列的末尾
參數 :msqid 消息隊列的標識符
msgp 發送的消息
struct msgbuf{
long mtype; 消息的類型
char mtext[1]; 消息的征文
};
msgsz 消息征文的大小
msgflg 0 消息隊列沒空間,寫操作阻塞
返回值 : 成功:0;失敗:-1;
3)將消息從隊列中移除
函數原型:ssize_t masrcv(int msqid,void *msgp,size_t msgsz,long msgtype,int msgflg);
參數 :msqid 消息隊列標識符
msgp 保存接受的消息(定義和寫入時保持一致)
msgsz 消息正文的大小
msgtype 消息的類型 0 讀取消息隊列中的第一個消息
>0 讀取消息隊列中類型為msgtype 的第一個消息
<0 讀取消息隊列中不小於msgtype 的絕對值,且類型最小的第一個消息
msgflg 0 消息隊列中無數據,讀操作阻塞
返回值:成功 消息正文的大小
失敗 -1
4)對消息隊列的控制
函數原型:int msgctl(int msqid,int cmd,struct msqid_ds *buf);
功能 :實現對消息隊列的控制
參數 :msqid 消息隊列的標識符
:cmd 制定消息隊列的操作處理
IPC_STAT 從第三個參數讀取消息隊列的屬性信息
IPC_SET 設置消息隊列的屬性
IPC_RMID 刪除消息隊列
:buf 描述消息隊列屬性的結構體
struct msqid_ds {
struct ipc_perm msg_perm; /* Ownership and permissions */ 消息隊列的權限
time_t msg_stime; /* Time of last msgsnd(2) */ 消息隊列發送消息的時間
time_t msg_rtime; /* Time of last msgrcv(2) */ 消息隊列接受消息的時間
time_t msg_ctime; /* Time of last change */ 消息隊列改變的時間
unsigned long __msg_cbytes; /* Current number of bytes in
queue (nonstandard) */ 消息隊列當前的字節數
msgqnum_t msg_qnum; /* Current number of messages
in queue */ 消息隊列當前消息的個數
msglen_t msg_qbytes; /* Maximum number of bytes
allowed in queue */ 消息隊列最大的字節數
pid_t msg_lspid; /* PID of last msgsnd(2) */ 發送消息的用戶ID
pid_t msg_lrpid; /* PID of last msgrcv(2) */ 接收消息的用戶ID
};
返回值:成功 0
失敗 -1
實現兩個終端數據交互(創建子進程)
2.共享內存
工作原理:系統為每一個進程創建4G的虛擬地址空間,共享內存開辟一塊實際的物理內存區域(共享內存區域)將該區域映射給每一個進程
本質 :多進程實際都是在訪問同一塊物理內存區域
其通信效率最高,適用場合:實現實時數據傳輸
多進程訪問同一塊物理內存區域,容易產生竟態,共享內存結合同步互斥機制,保證數據的正確性,任何一個時刻只有一個任務在訪問共享的內存區域
1)申請物理內存區域
函數原型:int shmget(key_t key,size_t size,int shmflg);
功能 :開辟實際物理內存區域
參數 :key: 來自ftok
:size 物理內存的大小
:shmflg IPC_CREAT|IPC_EXCK|0664 創建並打開物理內存(內存不存在,開辟;已存在,報錯)
返回值 :成功 共享內存的標識符
失敗 -1
2)將物理內存映射到進程的虛擬地址空間上(進程只需要操作屬於自己的虛擬地址空間,本質訪問實際物理內存)
函數原型: void *shmat(int shmid,const void *shmaddr,int shmflg);
功能 :將物理內存區域映射到進程的虛擬地址空間(將物理地址轉換為虛擬地址)
參數 :shmid 共享內存標識符
:shmaddr NULL 將物理內存映射進程一個合理的位置(未使用,且內存足夠大區域)
:shmflg 0 對於共享內存段,可以實現讀寫
返回值 :成功 鏈接物理內存的虛擬地址
失敗 -1
3)將物理內存釋放
函數原型:int shmctl(int shmid,int cmd,struct shmid_ds *buf);
功能 :實現對共享內存的控制
參數 :shmid 共享內存的標識符
:cmd 制定對共享內存的操作
IPC_STAT 從第三個參數中讀取共享內存的屬性信息
IPC_SET 設置共享內存的屬性信息
IPC_RMID 刪除共享內存
:buf 描述共享內存屬性的結構體
struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions */ 訪問的權限
size_t shm_segsz; /* Size of segment (bytes) */ 共享內存的大小
time_t shm_atime; /* Last attach time */ 上一次被映射的時間
time_t shm_dtime; /* Last detach time */ 上一次被斷開映射的時間
time_t shm_ctime; /* Last change time */ 上一次改變的時間
pid_t shm_cpid; /* PID of creator */ 創建共享內存的用戶ID
pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */ 上一次執行映射和斷開映射的進程ID
shmatt_t shm_nattch; /* No. of current attaches */ 被映射的次數(編號)
...
};
返回值:成功 0
失敗 -1
4.信號燈
信號燈:信號量集
信號量的核心:PV操作
1)創建多個信號量
函數原型:int semget(key_t key,int nsems,int semflg);
功能 :創建或打開多個信號量
參數 :key 值 ftok
:nsems 創建或打開信號量的個數
:semflg IPC_CREAT|IPC_EXCL|0664 創建並打開信號量(信號量存在,報錯,不存在,自動創建)
: 0664 打開信號量集的標識符
返回值: 成功:信號量集的標識符,失敗:-1
2)申請,釋放信號量
函數原型:int semop(int semid,struct sembuf *sops,unsigned nsops);
功能 :實現對信號量集的操作
參數 :semid 信號量集的標識符
: sops:
struct sembuf{
unsigned short sem_num; /* semaphore number */ 信號量的編號
short sem_op; /* semaphore operation */
1 釋放信號量 值+1
0 等待信號量的值變為0
-1 申請信號量 值-1
short sem_flg; /* operation flags */ 默認為0
}
nsops 本次函數操作的信號量的個數
返回值:成功 0
失敗 -1
3)信號量集的控制
函數原型:int semctl(int semid, int semnum, int cmd, ...);
功能:實現對信號量集中某一個信號量的控制
參數:semid 信號量集的標識符
semnum 信號量集信號量的編號
cmd 指定對信號量的控制
IPC_STAT 獲取信號量的屬性信息
IPC_SET 設置信號量的屬性信息
IPC_RMID 刪除信號量
SETVAL 設置第semnum個信號量的初始值
GETVAL 獲取第semnum個信號量的值
返回值:成功 0
GETVAL 當前信號量的值
失敗 -1
... 附件參數
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
信號量的屬性
truct semid_ds {
struct ipc_perm sem_perm; /* Ownership and permissions */ 訪問的權限
time_t sem_otime; /* Last semop time */ 上一次PV操作的時間
time_t sem_ctime; /* Last change time */ 上一次改變的時間
unsigned short sem_nsems; /* No. of semaphores in set */ 信號量集合中信號量個數
};
linux io 學習筆記(03)---共享內存,信號燈,消息隊列