Linux C 信号量
生活随笔
收集整理的這篇文章主要介紹了
Linux C 信号量
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 1、信號量的概念
- 1.1、二元信號量
- 2、函數介紹
- 2.1、semget函數
- 2.2、semctl函數
- 2.3、semop函數
- 3、示例代碼
- 4、其他操作
1、信號量的概念
用于協調多個進程(包括但不限于父子進程)對共享數據對象的讀/寫。它不以傳送數據為目的,主要是用來保護共享資源,保證共享資源在一個時刻只有一個進程獨享。
1.1、二元信號量
信號量是一個特殊的變量,只允許進程對它進行等待信號和發送信號操作。最簡單的信號量是取值0和1的二元信號量,這是信號量最常見的形式,1表示可以訪問,0表示加鎖
2、函數介紹
Linux中提供了一組函數用于操作信號量,程序中需要包含以下頭文件:
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>2.1、semget函數
semget函數用來獲取或創建信號量
typedef unsigned int key_t int semget(key_t key, int nsems, int semflg); 參數:key:是信號量的鍵值,是信號量在系統中的編號(一般用十六進制表示)nsems:是創建信號量集中信號量的個數,該參數只在創建信號量集時有效,這里固定填1。sem_flags:是一組標志,如果希望信號量不存在時創建一個新的信號量,可以和值IPC_CREAT做按位或操作。如果沒有設置IPC_CREAT標志并且信號量不存在,就會返錯(errno的值為2,No such file or directory)返回值:成功:返回信號量集的標識失敗:-1示例代碼: 1)獲取鍵值為0x5000的信號量,如果該信號量不存在,就創建它,代碼如下: int semid=semget(0x5000,1,0640|IPC_CREAT);2)獲取鍵值為0x5000的信號量,如果該信號量不存在,返回-1,errno的值被設置為2,代碼如下: int semid= semget(0x5000,1,0640);2.2、semctl函數
該函數用來控制信號量(常用于設置信號量的初始值和銷毀信號量
int semctl(int semid, int sem_num, int command, ...); 參數:semid: semget函數返回值sem_num: 是信號量集數組上的下標,表示某一個信號量,填0cmd: 是對信號量操作的命令種類,常用的有以下兩個:IPC_RMID:銷毀信號量,不需要第四個參數;SETVAL:初始化信號量的值(信號量成功創建后,需要設置初始值),這個值由第四個參數決定。第四參數是一個自定義的共同體,如下: // 用于信號燈操作的共同體。union semun{int val;struct semid_ds *buf;unsigned short *arry;};示例: 1)銷毀信號量。semctl(semid,0,IPC_RMID); 2)初始化信號量的值為1,信號量可用。union semun sem_union;sem_union.val = 1;semctl(semid,0,SETVAL,sem_union);2.3、semop函數
該函數有兩個功能:1)等待信號量的值變為1,如果等待成功,立即把信號量的值置為0,這個過程也稱之為等待鎖;2)把信號量的值置為1,這個過程也稱之為釋放鎖。
int semop(int semid, struct sembuf *sops, unsigned nsops); 參數:semid:semget函數返回的信號量標識sops:是一個結構體 struct sembuf {short sem_num; // 信號量集的個數,單個信號量設置為0。short sem_op; // 信號量在本次操作中需要改變的數據:-1-等待操作;1-發送操作。short sem_flg; // 把此標志設置為SEM_UNDO,操作系統將跟蹤這個信號量。// 如果當前進程退出時沒有釋放信號量,操作系統將釋放信號量,避免資源被死鎖。 };nsops:是操作信號量的個數,即sops結構變量的個數,設置它的為1(只對一個信號量的操作)示例: 1)等待信號量的值變為1,如果等待成功,立即把信號量的值置為0; struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = -1; sem_b.sem_flg = SEM_UNDO; semop(sem_id, &sem_b, 1);2)把信號量的值置為1。 struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = 1; sem_b.sem_flg = SEM_UNDO; semop(sem_id, &sem_b, 1);3、示例代碼
這段代碼從嚴格來說是錯誤的,因為我沒有加錯誤處理,這樣子寫主要是為了理解,大家看一下加深理解就好,
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>union semun // 用于信號量操作的共同體。 {int val;struct semid_ds *buf;unsigned short *arry; };int main() {int semid = semget(0x5000,1,0644|IPC_CREAT); // 創建或獲取信號量printf("semid:%d\n",semid); // 信號量idunion semun sem_union; // 設置信號量初始值sem_union.val = 1;semctl(semid,0,SETVAL,sem_union);int value = semctl(semid,0,GETVAL); // 獲取當前信號量的值printf("value:%d\n",value);struct sembuf sem_b;sem_b.sem_num = 0;sem_b.sem_op = -1;sem_b.sem_flg = SEM_UNDO; semop(semid,&sem_b,1); // 相當于加鎖操作// 設置完之后信號量值就變成0了,標識持有鎖int value1 = semctl(semid,0,GETVAL); // 獲取一下當前信號量值,當前值就是0printf("value1:%d\n",value1);sem_b.sem_num = 0; sem_b.sem_op = 1;sem_b.sem_flg = SEM_UNDO; semop(semid,&sem_b,1); // 釋放鎖操作// 設置完,信號量值為1int value2 = semctl(semid,0,GETVAL); // 獲取當前信號量值,當前值就是1printf("value1:%d\n",value2);return 0; }4、其他操作
1、用ipcs -s可以查看系統的信號量,內容有鍵值(key),信號量編號(semid),創建者(owner),權限(perms),信號量數(nsems)。2、用ipcrm sem 信號量編號,可以手工刪除信號量總結
以上是生活随笔為你收集整理的Linux C 信号量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言使用信号量(Linux)
- 下一篇: Linux C 下的socket网络编程