一、獲取信號量
用semget()函數(shù)獲取信號量,其中semget()函數(shù)中所需傳的參數(shù)如下:
semget(key_t key , int nsems, semflg);
參數(shù)解釋:
1、其中key可以通過ftok()?函數(shù)進(jìn)行獲取,ftok函數(shù)所需傳入的參數(shù)為①文件路徑②一個八位的整數(shù)
2、nsems是所需創(chuàng)建的信號量的個數(shù),如果只是訪問已存在的信號量集合,可以將此參數(shù)設(shè)置為0。
3、semflg是一個標(biāo)志參數(shù),用于指定創(chuàng)建或訪問信號量集合的方式,常用的標(biāo)志有:
①IPC_CREAT:如果指定的鍵值對應(yīng)的信號量集合不存在,則創(chuàng)建一個新的信號量集合。
②IPC_EXCL:與IPC_CREAT同時使用,如果指定的鍵值對應(yīng)的信號量集合已經(jīng)存在,則返回錯誤。
③0666:用于指定信號量集合的權(quán)限,表示允許所有用戶讀寫信號量集合,這里也可以是填其它權(quán)限,如0664等,不一定是0666
具體實現(xiàn):
int sem_creat(key_t key, int nsems)
{
int semid = semget(key, nsems, 0664|IPC_CREAT);//創(chuàng)建信號量
if(semid < 0){ //通過返回值判斷信號量是否創(chuàng)建成功,小于零則創(chuàng)建失敗,打印一下錯誤信息并退出
perror("semget");
exit(0);
}
return semid;
}
二、初始化信號量
用semctl來初始化信號量,其中semctl函數(shù)所需傳入的參數(shù)如下:
int semctl(int semid, int semnum, int cmd, ...)
:
參數(shù)解釋:?
1、semid:信號量集合的標(biāo)識符,通過smget函數(shù)獲?。ㄒ簿褪巧弦徊将@取信號量的時候得到的)。
2、semnum:要操作的信號量在集合中的索引(也就是要初始化哪一個信號量),對于一個信號量集合可以有多個信號量,而semnum指定了要操作的具體信號量
3、cmd:指定要執(zhí)行的命令,可以是以下幾種之一:
①、GETVAL
:獲取指定信號量的當(dāng)前值。
②、SETVAL
:設(shè)置指定信號量的值。
③、IPC_RMID
:刪除信號量集合。
④、IPC_STAT
:獲取信號量集合的狀態(tài)信息。
⑤、IPC_SET
:設(shè)置信號量集合的狀態(tài)信息。
⑥、GETALL
:獲取所有信號量的當(dāng)前值。
⑦、SETALL
:設(shè)置所有信號量的值。
4、....:表示可變參數(shù),根據(jù)不同的命令有不同的使用方式,需要注意的是。semctl函數(shù)的第四個參數(shù)arg的具體含義取決于使用命令和使用方式(也就是根據(jù)第三個參數(shù)來的),對于某些命令,arg是一個整數(shù)值,而對于其它命令,arg是一個指向union semun結(jié)構(gòu)體的指針。在使用semctl函數(shù)時,需要根據(jù)具體的需求和命令來確定如何使用這個參數(shù)。
具體實現(xiàn):
void init_sem(int semid,int semnum,int val)//初始化需要傳semid和初始化哪個信號量,還有初始化的值
{
int ret;
union semun sem;//這個是根據(jù)第三個參數(shù)來的,semun聯(lián)合體中有好多種數(shù)據(jù)類型
sem.val = val;
ret = semctl(semid,semnum,SETVAL,sem);//這里用的是SETVAL,所以要傳第四個參數(shù),也就是你要初始化的值
if(ret < 0)//判斷是否初始化成功
{
perror("semctl");
exit(0);
}
}
注意:?union semun聯(lián)合體(也叫共用體)需要我們自己去實現(xiàn),大概的樣子長這樣:
union semun {
int val; // 設(shè)置信號量的初始值或獲取當(dāng)前值
struct semid_ds *buf; // IPC_STAT 或 IPC_SET 時使用
unsigned short *array; // GETALL 或 SETALL 時使用
};
三、進(jìn)行p操作(加鎖操作)
用semop函數(shù)來進(jìn)行加鎖操作,semop函數(shù)傳入的參數(shù)如下:
?int semop(int semid, struct sembuf *sops, size_t nsops);
參數(shù)解釋:?
1、semid:是一個信號量集標(biāo)識符,用于指定要操作的信號量集。在使用semget
函數(shù)創(chuàng)建信號量集后,會返回該標(biāo)識符。
2、sops
:是一個指向sembuf
結(jié)構(gòu)體數(shù)組的指針,每個sembuf
結(jié)構(gòu)體表示對一個信號量的操作(也就是通過結(jié)構(gòu)體來設(shè)置信號量當(dāng)前的狀態(tài))。
sembuf結(jié)構(gòu)體的定義如下:
struct sembuf {
unsigned short sem_num; // 信號量在信號量集中的索引
short sem_op; // 信號量的操作
short sem_flg; // 操作標(biāo)志
};
其中
sem_num是要操作的信號量在信號量集中的索引,從0開始計數(shù)
sem_op
:是對信號量的操作,可以是正整數(shù)、負(fù)整數(shù)或零。
·??正整數(shù)表示將信號量的值增加相應(yīng)的數(shù)量。
·??負(fù)整數(shù)表示將信號量的值減少相應(yīng)的數(shù)量。
·??零表示等待信號量變?yōu)榱恪?/p>
?sem_flg是操作標(biāo)志,用于指定操作的行為,常見的取值有:
-
SEM_UNDO
:如果進(jìn)程退出時仍然持有該信號量,則會自動釋放。 -
IPC_NOWAIT
:如果無法立即執(zhí)行操作,則函數(shù)會立即返回,并設(shè)置錯誤碼為EAGAIN
。
3、nsops
:表示sembuf
結(jié)構(gòu)體數(shù)組中元素的數(shù)量,即要進(jìn)行操作的信號量的個數(shù)。
具體實現(xiàn):
void sem_p(int semid,int semnum,size_t nsops)
{
struct sembuf sops;
sops.sem_num = semnum;//設(shè)置要操作哪個信號量
sops.sem_op = -1;//設(shè)置信號量要執(zhí)行的操作,-1是上鎖的操作,鎖-1
sops.sem_flg = SEM_UNDO;//防止死鎖‘
int ret = semop(semid,&sops,nsops);
if(ret < 0)//判斷是否執(zhí)行成功
{
perror("semop-p");
exit(0);
}
}
四、進(jìn)行v操作(解鎖操作)?
進(jìn)行v操作也是用的semop函數(shù),只是傳的參數(shù)不同,sops.sem_op = 1。文章來源:http://www.zghlxwxcb.cn/news/detail-635275.html
具體實現(xiàn):
void sem_v(int semnum,size_t nsops)
{
struct sembuf sops;
sops.sem_num = semnum;
sops.sem_op = +1;//與p操作不同的地方
sops.sem_flg = SEM_UNDO;
int ret = semop(semid,&sops,nsops);
if(ret < 0)
{
perror("semop-v");
exit(0);
}
}
五、釋放信號量
釋放信號量也可以用semctl()函數(shù),只是傳的參數(shù)有變化文章來源地址http://www.zghlxwxcb.cn/news/detail-635275.html
具體實現(xiàn):
void sem_destroy(int semid)
{
int ret = semctl(semid,-1,IPC_RMID);
if(ret < 0)
{
perror("semctl-rmid");
exit(0);
}
}
到了這里,關(guān)于C語言用信號量進(jìn)行pv操作的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!