溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Linux中的semaphore是什么

發(fā)布時(shí)間:2022-01-27 15:14:23 來源:億速云 閱讀:497 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)Linux中的semaphore是什么的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

Semaphore 通常我們叫它信號量, 可以用來控制同時(shí)訪問特定資源的線程數(shù)量,通過協(xié)調(diào)各個(gè)線程,以保證合理的使用資源。

Linux中的semaphore是什么

1.信號量

信號量本質(zhì)上是一個(gè)計(jì)數(shù)器(不設(shè)置全局變量是因?yàn)檫M(jìn)程間是相互獨(dú)立的,而這不一定能看到,看到也不能保證++引用計(jì)數(shù)為原子操作),用于多進(jìn)程對共享數(shù)據(jù)對象的讀取,它和管道有所不同,它不以傳送數(shù)據(jù)為主要目的,它主要是用來保護(hù)共享資源(信號量也屬于臨界資源),使得資源在一個(gè)時(shí)刻只有一個(gè)進(jìn)程獨(dú)享。

2.信號量的工作原理

由于信號量只能進(jìn)行兩種操作等待和發(fā)送信號,即P(sv)和V(sv),他們的行為是這樣的:

(1)P(sv):如果sv的值大于零,就給它減1;如果它的值為零,就掛起該進(jìn)程的執(zhí)行

(2)V(sv):如果有其他進(jìn)程因等待sv而被掛起,就讓它恢復(fù)運(yùn)行,如果沒有進(jìn)程因等待sv而掛起,就給它加1.

在信號量進(jìn)行PV操作時(shí)都為原子操作(因?yàn)樗枰Wo(hù)臨界資源)

注:原子操作:單指令的操作稱為原子的,單條指令的執(zhí)行是不會被打斷的

3.二元信號量

二元信號量(Binary Semaphore)是最簡單的一種鎖(互斥鎖),它只用兩種狀態(tài):占用與非占用。所以它的引用計(jì)數(shù)為1。

4.進(jìn)程如何獲得共享資源

(1)測試控制該資源的信號量

(2)信號量的值為正,進(jìn)程獲得該資源的使用權(quán),進(jìn)程將信號量減1,表示它使用了一個(gè)資源單位

(3)若此時(shí)信號量的值為0,則進(jìn)程進(jìn)入掛起狀態(tài)(進(jìn)程狀態(tài)改變),直到信號量的值大于0,若進(jìn)程被喚醒則返回至第一步。

注:信號量通過同步與互斥保證訪問資源的一致性。

5.與信號量相關(guān)的函數(shù)

所有函數(shù)共用頭文件

 #include #include #include

5.1創(chuàng)建信號量

 int` `semget(key_t key,``int` `nsems,``int` `flags)``                 ``//返回:成功返回信號集ID,出錯(cuò)返回-1

  

(1)第一個(gè)參數(shù)key是長整型(唯一非零),系統(tǒng)建立IPC通訊 ( 消息隊(duì)列、 信號量和 共享內(nèi)存) 時(shí)必須指定一個(gè)ID值。通常情況下,該id值通過ftok函數(shù)得到,由內(nèi)核變成標(biāo)識符,要想讓兩個(gè)進(jìn)程看到同一個(gè)信號集,只需設(shè)置key值不變就可以。

(2)第二個(gè)參數(shù)nsem指定信號量集中需要的信號量數(shù)目,它的值幾乎總是1。

(3)第三個(gè)參數(shù)flag是一組標(biāo)志,當(dāng)想要當(dāng)信號量不存在時(shí)創(chuàng)建一個(gè)新的信號量,可以將flag設(shè)置為IPC_CREAT與文件權(quán)限做按位或操作。 設(shè)置了IPC_CREAT標(biāo)志后,即使給出的key是一個(gè)已有信號量的key,也不會產(chǎn)生錯(cuò)誤。而IPC_CREAT | IPC_EXCL則可以創(chuàng)建一個(gè)新的,唯一的信號量,如果信號量已存在,返回一個(gè)錯(cuò)誤。一般我們會還或上一個(gè)文件權(quán)限

5.2刪除和初始化信號量

 int` `semctl(``int` `semid, ``int` `semnum, ``int` `cmd, ...);

如有需要第四個(gè)參數(shù)一般設(shè)置為union semnu arg;定義如下

 union semun
 { 
     int val;  //使用的值
     struct semid_ds *buf;  //IPC_STAT、IPC_SET 使用的緩存區(qū)
     unsigned short *arry;  //GETALL,、SETALL 使用的數(shù)組
     struct seminfo *__buf; // IPC_INFO(Linux特有) 使用的緩存區(qū)
 };

  

(1)sem_id是由semget返回的信號量標(biāo)識符

(2)semnum當(dāng)前信號量集的哪一個(gè)信號量

(3)cmd通常是下面兩個(gè)值中的其中一個(gè) SETVAL:用來把信號量初始化為一個(gè)已知的值。p 這個(gè)值通過union semun中的val成員設(shè)置,其作用是在信號量第一次使用前對它進(jìn)行設(shè)置。 IPC_RMID:用于刪除一個(gè)已經(jīng)無需繼續(xù)使用的信號量標(biāo)識符,刪除的話就不需要缺省參數(shù),只需要三個(gè)參數(shù)即可。

5.3改變信號量的值

 int` `semop(``int` `semid, ``struct` `sembuf *sops, ``size_t` `nops);

  

(1)nsops:進(jìn)行操作信號量的個(gè)數(shù),即sops結(jié)構(gòu)變量的個(gè)數(shù),需大于或等于1。最常見設(shè)置此值等于1,只完成對一個(gè)信號量的操作

(2)sembuf的定義如下:

 struct sembuf{ 
     short sem_num;   //除非使用一組信號量,否則它為0 
     short sem_op;   //信號量在一次操作中需要改變的數(shù)據(jù),通常是兩個(gè)數(shù),                                        
                     //一個(gè)是-1,即P(等待)操作, 
                     //一個(gè)是+1,即V(發(fā)送信號)操作。 
     short sem_flg; //通常為SEM_UNDO,使操作系統(tǒng)跟蹤信號量, 
                   //并在進(jìn)程沒有釋放該信號量而終止時(shí),操作系統(tǒng)釋放信號量 
 };

  

5.4sembuf中sem_flg的設(shè)置問題

通常設(shè)置為SEM_UNDO,使操作系統(tǒng)跟蹤信號量, 并在進(jìn)程沒有釋放該信號量而終止時(shí),操作系統(tǒng)釋放信號量 ,例如在二元信號量中,你不釋放該信號量 而異常退出,就會導(dǎo)致別的進(jìn)程一直申請不到信號量,而一直處于掛起狀態(tài)。

是否設(shè)置sem_flg為SEM_UNDO的區(qū)別

Linux中的semaphore是什么

6.模擬實(shí)現(xiàn)信號量實(shí)現(xiàn)進(jìn)程間通信

用一個(gè)上課的時(shí)候講過的簡單的例子來說明一下:

 #include #include #include #include #define total 20
 sem_t remain, apple, pear, mutex;
 static unsigned int vremain = 20, vapple = 0, vpear = 0;
 void *father(void *);
 void *mather(void *);
 void *son(void *);
 void *daughter(void *);
 void print_sem();
 int main()
 {  
     pthread_t fa, ma, so, da;  
     sem_init(&remain, 0, total);//總數(shù)初始化為20 
     sem_init(&apple, 0, 0);//盆子中蘋果數(shù), 開始為0  
     sem_init(&pear, 0, 0);//盆子中梨子數(shù), 開始為0   
     sem_init(&mutex, 0, 1);//互斥鎖, 初始為1 
     pthread_create(&fa, NULL, &father, NULL);  
     pthread_create(&ma, NULL, &mather, NULL);  
     pthread_create(&so, NULL, &son, NULL); 
     pthread_create(&da, NULL, &daughter, NULL);    
     for(;;);
 }
 void *father(void *arg)
 {  
     while(1)
     {      
         sem_wait(&remain);     
         sem_wait(&mutex);      
         printf("父親: 放蘋果之前, 剩余空間=%u, 蘋果數(shù)=%u\n", vremain--, vapple++);
         printf("父親: 放蘋果之后, 剩余空間=%u, 蘋果數(shù)=%u\n", vremain, vapple);
         sem_post(&mutex);      
         sem_post(&apple);  
         sleep(1);  
     }
 }
 void *mather(void *arg)
 {  
     while(1)
     {      
         sem_wait(&remain);     
         sem_wait(&mutex);      
         printf("母親: 放梨子之前, 剩余空間=%u, 梨子數(shù)=%u\n", vremain--, vpear++);
         printf("母親: 放梨子之后, 剩余空間=%u, 梨子數(shù)=%u\n", vremain, vpear);
         sem_post(&mutex);  
         sem_post(&pear);   
         sleep(2);  
     }
 }
 void *son(void *arg)
 {  
     while(1)
     {      
         sem_wait(&pear);   
         sem_wait(&mutex);   
         printf("兒子: 吃梨子之前, 剩余空間=%u, 梨子數(shù)=%u\n", vremain++, vpear--);
         printf("兒子: 吃梨子之后, 剩余空間=%u, 梨子數(shù)=%u\n", vremain, vpear);
         sem_post(&mutex);  
         sem_post(&remain);     
         sleep(3);
     }
 }
 void *daughter(void *arg)
 {  
     while(1)
     {  
         sem_wait(&apple);  
         sem_wait(&mutex);
         printf("女兒: 吃蘋果之前, 剩余空間=%u, 蘋果數(shù)=%u\n", vremain++, vapple--);
         printf("女兒: 吃蘋果之前, 剩余空間=%u, 蘋果數(shù)=%u\n", vremain, vapple);   
         sem_post(&mutex);  
         sem_post(&remain); 
         sleep(3);  
     }
 }
 void print_sem()
 {  
     int val1, val2, val3;
     sem_getvalue(&remain, &val1);  
     sem_getvalue(&apple, &val2);   
     sem_getvalue(&pear, &val3);
     printf("Semaphore: remain:%d, apple:%d, pear:%d\n", val1, val2, val3);
 }

  編譯時(shí)記得要加上 -lpthread 否則sem_ 都是未定義的。

因?yàn)樵谥骱瘮?shù)中做了一個(gè)死循環(huán)所以這個(gè)程序會一直跑下去

Linux中的semaphore是什么

感謝各位的閱讀!關(guān)于“Linux中的semaphore是什么”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI