日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

C语言使用信号量(Linux)

發(fā)布時(shí)間:2023/12/31 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言使用信号量(Linux) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在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ù)具體用法可以使用命令查看:

man pthread_cond_wait #或者 man function

鎖操作可以實(shí)現(xiàn)互斥訪問,條件變量可以實(shí)現(xiàn)進(jìn)程同步功能,因此這些函數(shù)可以組成信號量操作,函數(shù)具體內(nèi)容就不再贅述。
首先定義信號量結(jié)構(gòu)體:

typedef struct {int value;pthread_mutex_t mutex;//信號量為原子操作pthread_cond_t cond; }sema_t;

value表示資源量,mutex實(shí)現(xiàn)原子操作,cond實(shí)現(xiàn)阻塞等待以及喚醒。
P操作即首先占用一個(gè)資源量,如果不夠則阻塞,資源夠用立即返回:

void sema_wait(sema_t *sema) {pthread_mutex_lock(&sema->mutex);sema->value--;while(sema->value<0)pthread_cond_wait(&sema->cond,&sema->mutex);pthread_mutex_unlock(&sema->mutex);}

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ū)滿

void *produce() {int item;for(int i=0;i<item_count;i++){sema_wait (&wait_empty_buff1);sema_wait (&mutex1);item='a'+i;put_item(1,item);printf("Produce item: %c\n",item);sema_signal (&mutex1);sema_signal (&wait_full_buff1);}return NULL; }

consume線程與produce類似,也有如上述三個(gè)要求,但是是2、3是相反的并且互斥訪問buff2:
1.buff2互斥訪問
2.緩沖區(qū)空不能拿
3.拿完通知緩沖區(qū)空

void *consume() {int item;for(int i=0;i<item_count;i++){sema_wait (&wait_full_buff2);sema_wait (&mutex2);item=get_item(2);printf("Consume item: %c\n",item);sema_signal (&mutex2);sema_signal (&wait_empty_buff2);}return NULL; }

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不能滿。
信號量初始化:

mutex1.value=1;//互斥訪問,一次只能允許一個(gè) mutex2.value=1; wait_empty_buff1.value=bsize-1;//緩沖區(qū)大小-1 wait_empty_buff2.value=bsize-1; wait_full_buff1.value=0;//沒有寫數(shù)據(jù)時(shí)為空 wait_full_buff2.value=0;

至此全部完畢。
題目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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。