C语言使用信号量(Linux)
在windows中使用信號量已經(jīng)在另一篇文章中講過了,信號量的詳細(xì)細(xì)節(jié)也已經(jīng)展示了,本文介紹如何在linux環(huán)境下使用c語言編寫信號量類型的例子代碼。
windows c語言使用信號量
與windows環(huán)境下不同,在linux下,頭文件unistd.h或者pthread.h都沒有直接包含P,V操作,也就是wait(),signal(),也即信號量的P,V操作需要自行編程實(shí)現(xiàn)。信號量結(jié)構(gòu)體(參考上面鏈接)已經(jīng)清楚,但是這還不夠,實(shí)現(xiàn)信號量需要滿足以下兩個(gè)條件:
1.信號量操作只能是原子操作
2.除了P,V操作外,其他函數(shù)無法操作信號量
我們先看Linux下C語言提供的相關(guān)函數(shù):
1.pthread_t; 2.pthread_mutex_t; 3.pthread_cond_t; 4.pthread_mutex_lock(); 5.pthread_mutex_unlock(); 6.pthread_cond_wait(); 7.pthread_cond_signal(); 8.pthread_mutex_init(); 9.pthread_cond_init();1-3為相關(guān)變量定義,4、5為互斥訪問的鎖操作,6、7為條件變量,8、9為初始化函數(shù)。
函數(shù)具體用法可以使用命令查看:
鎖操作可以實(shí)現(xiàn)互斥訪問,條件變量可以實(shí)現(xiàn)進(jìn)程同步功能,因此這些函數(shù)可以組成信號量操作,函數(shù)具體內(nèi)容就不再贅述。
首先定義信號量結(jié)構(gòu)體:
value表示資源量,mutex實(shí)現(xiàn)原子操作,cond實(shí)現(xiàn)阻塞等待以及喚醒。
P操作即首先占用一個(gè)資源量,如果不夠則阻塞,資源夠用立即返回:
V操作首先釋放一個(gè)資源量,并調(diào)喚醒一個(gè)條件變量,這里不用判斷有沒有被阻塞的進(jìn)程,條件變量cond已經(jīng)幫你實(shí)現(xiàn)了:
void sema_signal(sema_t *sema) {pthread_mutex_lock(&sema->mutex);sema->value++;pthread_cond_signal(&sema->cond);pthread_mutex_unlock(&sema->mutex); }這樣就完整實(shí)現(xiàn)了P,V操作。
下面看一個(gè)使用信號量的例子:
- 系統(tǒng)中有3個(gè)線程:生產(chǎn)者、計(jì)算者、消費(fèi)者
- 系統(tǒng)中有2個(gè)容量為4的緩沖區(qū):buffer1、buffer2
- 生產(chǎn)者
- 生產(chǎn)’a’、‘b’、‘c’、‘d’、‘e’、‘f’、‘g’、'h’八個(gè)字符
- 放入到buffer1
- 打印生產(chǎn)的字符
- 計(jì)算者
- 從buffer1取出字符
- 將小寫字符轉(zhuǎn)換為大寫字符,按照 input:OUTPUT 的格式打印
- 放入到buffer2
- 消費(fèi)者
- 從buffer2取出字符
- 打印取出的字符
- 程序輸出結(jié)果(實(shí)際輸出結(jié)果是交織的)
很明顯,需要五個(gè)信號量:
sema_t mutex1,mutex2;//互斥訪問緩沖區(qū) sema_t wait_empty_buff1; sema_t wait_full_buff1; sema_t wait_empty_buff2; sema_t wait_full_buff2;produce線程負(fù)責(zé)向buffer1中寫數(shù)據(jù),有幾個(gè)要求:
1.buff1互斥訪問
2.緩沖區(qū)滿不能寫
3.寫完通知緩沖區(qū)滿
consume線程與produce類似,也有如上述三個(gè)要求,但是是2、3是相反的并且互斥訪問buff2:
1.buff2互斥訪問
2.緩沖區(qū)空不能拿
3.拿完通知緩沖區(qū)空
compute比較復(fù)雜,是上述兩個(gè)線程的結(jié)合體,代碼如下:
void *compute() {int item,item_res;for(int i=0;i<item_count;i++){sema_wait (&wait_full_buff1);sema_wait (&mutex1);item=get_item(1);sema_signal (&mutex1);sema_signal (&wait_empty_buff1);item_res=item-('a'-'A');printf("Compute item: %c-->%c\n",item,item_res);sema_wait (&wait_empty_buff2);sema_wait (&mutex2);put_item(2,item_res);sema_signal (&mutex2);sema_signal (&wait_full_buff2);}return NULL; }由buff1拿出計(jì)算后放入buff2,拿的時(shí)候buff1不能空,放的時(shí)候buff2不能滿。
信號量初始化:
至此全部完畢。
題目2:
系統(tǒng)中有2個(gè)線程:ping 線程和 pong 線程
- ping 線程先執(zhí)行
- ping 線程執(zhí)行流程如下
- 打印輸出 ping
- 等待 pong 線程輸出
- 執(zhí)行第 1 步
- pong 線程執(zhí)行流程如下
- 打印輸出 pong
- 等待 ping 線程輸出
- 執(zhí)行第 1 步
- 程序輸出結(jié)果
ping
pong
ping
pong
…
想法類似,讀者可以自行實(shí)現(xiàn)
全部完整代碼地址
總結(jié)
以上是生活随笔為你收集整理的C语言使用信号量(Linux)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: KITTY数据集 下载 及 使用
- 下一篇: Linux C 信号量