亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 操作系統 > 正文

進程間通信之POSIX信號量

2024-06-28 13:27:52
字體:
來源:轉載
供稿:網友
進程間通信之POSIX信號量

POSIX信號量接口,意在解決XSI信號量接口的幾個不足之處:

  • POSIX信號量接口相比于XSI信號量接口,允許更高性能的實現。
  • POSIX信號量接口簡單易用:沒有信號量集,其中一些接口模仿了我們熟悉的文件系統操作。
  • POSIX信號量刪除時的處理更加合理。XSI信號量被刪除后,使用該信號量標識符的操作將會出錯返回,并將errno設置為EIDRM。而對于POSIX信號量,操作可以繼續正常執行,直到對該信號量的最后一個引用被釋放。

POSIX信號量有兩種形式可供選用:有名和無名。它們的區別在于,如何被創建和銷毀,其他方面則完全相同。無名信號量只存在于內存中,并且規定能夠訪問該內存的進程才能夠使用該內存中的信號量。這就意味著,無名信號量只能被這樣兩種線程使用:(1)來自同一進程的各個線程(2)來自不同進程的各個線程,但是這些進程映射了相同的內存范圍到自己的地址空間。相反,有名信號量則是通過名字訪問,因此,來自于任何進程的線程,只要知道該有名信號量的名字都可以訪問。

調用sem_open函數可以創建一個新的有名信號量,或打開一個現存的有名信號量。

#include <semaphore.h>sem_t *sem_open(const char *name, int oflag, ... /* mode_t mode, unsigned int value */ );返回值:若成功則返回指向信號量的指針,若出錯則返回SEM_FAILED

如果使用一個現存的有名信號量,我們只需指定兩個參數:信號量名和oflag(oflag取0)。把oflag設置為O_CREAT標志時,如果指定的信號量不存在則新建一個有名信號量;如果指定的信號量已經存在,那么打開使用,無其他額外操作發生。

如果我們指定O_CREAT標志,那么就需要提供另外兩個參數:mode和value。mode用來指定誰可以訪問該信號量。它可以取打開文件時所用的權限位的取值(參考http://www.CUOXin.com/nufangrensheng/p/3502097.html中表4-5)。最終賦予信號量的訪問權限,是被調用者文件創建屏蔽字所修改過的(http://www.CUOXin.com/nufangrensheng/p/3502328.html)。然而,注意通常只有讀寫權限對我們有用,但是接口不允許在我們打開一個現存的信號量時指定打開模式(mode)。實現通常以讀寫打開信號量。

value參數用來指定信號量的初始值。它可取值為:0-SEM_VALUE_MAX。

如果我們想要確保我們在創建一個新的信號量,可以把oflag參數設置為:O_CREAT|O_EXCL。如果信號量已經存在的話,這會導致sem_open調用失敗。

為了提高移植性,我們在選擇信號量名字的時候,必須遵循一定的約定:

  • 名字的首字符必須是斜杠(/)。
  • 除首字符外,名字中不能再包含其他斜杠(/)。
  • 名字的最長長度由實現定義,不應超過_POSIX_NAME_MAX個字符。

sem_open函數返回一個信號量指針,該指針可供其他對該信號量進行操作的函數使用。使用完成后,調用sem_close函數釋放與信號量相關的資源。

#include <semaphore.h>int sem_close(sem_t *sem);返回值:若成功則返回0,出錯返回-1

如果進程還沒有調用sem_close就已經退出,那么內核會自動關閉該進程打開的所有信號量。注意,這并不會影響信號量值的狀態——例如,如果我們增加了信號量的值,我們退出后這個值不會改變。同樣,如果我們調用了sem_close,信號量值也不會受到影響。POSIX信號量機制中并沒有如同XSI信號量中的SEM_UNDO標志。

調用sem_unlink函數來銷毀一個有名信號量。

#include <semaphore.h>int sem_unlink(const char *name);返回值:若成功則返回0,出錯則返回-1

sem_unlink函數移除信號量的名字。如果當前沒有打開的對該信號量的引用,那么就銷毀它。否則,銷毀被推遲到最后一個打開的引用被關閉。

與XSI信號量不同,我們只能對POSIX信號量的值進行加1或減1。對信號量值減1,就類似于對一個二值信號量加鎖或請求一個與計數信號量相關的資源。

注意,POSIX信號量并沒有區分信號量類型。使用二值信號量還是計數信號量,取決于我們如果對信號進行初始化和使用。如果信號量值只能取0和1,那么它就是一個二值信號量。當一個二值信號量值為1,我們則說它未加鎖;若它的值為0,則說它已加鎖。

調用sem_wait或sem_trywait函數,請求一個信號量(對信號量值執行減1操作)。

#include <semaphore.h>int sem_trywait(sem_t *sem);int sem_wait(sem_t *sem);兩個函數返回值:若成功則返回0,出錯則返回-1

如果信號量計數為0,這時如果調用sem_wait函數,將會阻塞。直到成功對信號量計數減1或被一個信號中斷,sem_wait函數才會返回。我們可以使用sem_trywait函數以避免阻塞。當我們調用sem_trywait函數時,如果信號量計數為0,sem_trywait會返回-1,并將errno設置為EAGAIN。

第三種方法是可以阻塞一段有限的時間,這時我們使用sem_timedwait函數。

#include <semaphore.h>#include <time.h>int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict tsptr);返回值:若成功則返回0,出錯則返回-1

tsptr參數指定了希望等待的絕對時間。如果信號量可以被立即減1,那么超時也無所謂,即使你指定了一個已經過去的時間,試圖對信號量減1的操作也會成功。如果直到超時,還不能對信號量計數減1,那么sem_timedwait函數將會返回-1,并將errno設置為ETIMEDOUT。

調用sem_post函數對信號量值加1。這類似于對一個二值信號量解鎖或釋放一個與計數信號量有關的資源。

#include <semaphore.h>int sem_post(sem_t *sem);返回值:若成功則返回0,出錯則返回-1

當我們調用sem_post的時,如果此時有因為調用sem_wait或sem_timedwait而阻塞的進程,那么該進程將被喚醒,并且剛剛被sem_post加1的信號量計數緊接著又被sem_wait或sem_timedwait減1。

如果我們想要在一個單一進程內使用POSIX信號量,那么使用無名信號量會更加簡單。無名信號量只是創建和銷毀有所改變,其他完全和有名信號量一樣。我們調用sem_init函數創建一個無名信號量。

#include <semaphore.h>int sem_init(sem_t *sem, int pshared, unsigned int value);返回值:若成功則返回0,出錯返回-1

pshared參數指示我們是否要在多進程之間使用該無名信號量。如果要在多個進程之間使用,則將pshared設置為非0值。value參數指定信號量的初始值。

另外,我們需要聲明一個sem_t類型的變量,并把它的地址傳給sem_init,以便對該變量進行初始化。如果我們要在兩個進程之間使用該無名信號量,我們需要確保sem參數指向這兩個進程共享的內存范圍內。

我們可以調用sem_destroy函數來銷毀用完的無名信號量。

#include <semaphore.h>int sem_destroy(sem_t *sem);返回值:若成功則返回0,出錯則返回-1

調用sem_destroy后我們將不能再以sem為參數調用任何信號量函數,除非我們再次使用sem_init對sem進行初始化。

我們可以調用sem_getvalue函數來獲取信號量值。

#include <semaphore.h>int sem_getvalue(sem_t *sem, int *restrict valp);返回值:若成功則返回0,出錯則返回-1

如果sem_getvalue執行成功,信號量的值將存入valp指向的整型變量中。但是,需要小心,我們剛讀出來的信號量值可能會改變(因為我們隨時可能會使用該信號量值)。如果不采取額外的同步機制的話,sem_getvalue函數僅僅用來調試。

實例

回憶http://www.CUOXin.com/nufangrensheng/p/3523623.html的表12-4,Single UNIX Specification并沒有定義當一個線程鎖定了一個normal類型的mutex,而另外一個線程試圖對此mutex進行解鎖會發生什么(對應于表12-4中“不占用時解鎖”欄)。但是對于error-checking類型和recursive類型的mutex,在這種情況下則會出錯。因為二值信號量可以像互斥量(mutex)一樣使用,我們可以使用信號量創建我們自己的鎖原語(PRimitive)來提供互斥。

假定我們要創建自己的鎖:它可以被一個線程加鎖,而被另外一個線程解鎖。我們的鎖結構可以如下:

struct slock {    sem_t    *semp;    char     name[_POSIX_NAME_MAX];};

程序清單15-35顯示了一種基于信號量的互斥原語的實現。

程序清單15-35 使用POSIX信號量的互斥

#include "slock.h"#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <error.h>struct slock *s_alloc(){    struct slock *sp;    static int    cnt;        if((sp = malloc(sizeof(struct slock))) == NULL)        return(NULL);    do    {        snprintf(sp->name, sizeof(sp->name), "/%ld.%d", (long)getpid(),            cnt++);        sp->semp =sem_open(sp->name, O_CREAT|O_EXCL, S_IRWXU, 1);    }    while((sp->semp == SEM_FAILED) && (errno == EEXIST));    if(sp->semp == SEM_FAILED)    {        free(sp);        return(NULL);    }    sem_unlink(sp->name);    return(sp);}voids_free(struct slock *sp){    sem_close(sp->semp);    free(sp);}int s_lock(struct slock *sp){    return(sem_wait(sp->semp));}ints_trylock(struct slock *sp){    return(sem_trywait(sp->semp));}ints_unlock(struct slock *sp){    return(sem_post(sp->semp));}

我們基于進程ID和計數counter創建一個名字。我們無需使用互斥量對counter加以保護,因為如果兩個相互競爭的線程同時調用s_alloc并且分配了相同的名字,但是使用O_EXCL標志調用sem_open時只會有一個調用成功,而另一個以EEXIST出錯返回,這時我們只需重新調用一次就行了。注意,我們在打開信號量后隨即銷毀它。這樣其他進程就不能再訪問它,而且簡化了進程結束時的清理工作。

本篇博文內容摘自《UNIX環境高級編程》(第3版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产香蕉精品视频一区二区三区| 欧美诱惑福利视频| 国产成人综合精品| 亚洲人a成www在线影院| 欧美日韩在线第一页| www.亚洲成人| 欧美精品免费看| 亚洲女性裸体视频| 中文字幕亚洲图片| 欧美又大粗又爽又黄大片视频| 一区二区欧美久久| 日韩在线观看你懂的| 久久精品视频网站| 国产精品视频yy9099| 日韩中文字幕在线视频播放| 国产成人亚洲综合青青| 国模精品系列视频| 最新91在线视频| 日韩精品丝袜在线| 国产欧美一区二区白浆黑人| 欧美日韩裸体免费视频| 国产一区二区三区在线看| 一区二区欧美日韩视频| 亚洲自拍小视频免费观看| 中日韩午夜理伦电影免费| 韩国三级电影久久久久久| 成人激情春色网| 久久成年人免费电影| 岛国av一区二区| 欧美另类99xxxxx| 欧美又大又粗又长| 欧美一级大片视频| 日韩av免费在线| 亚洲免费av电影| 日韩av在线资源| 大伊人狠狠躁夜夜躁av一区| 国产精品一区二区三区久久久| 久久精品99国产精品酒店日本| 亚洲人成毛片在线播放| 国产精品专区第二| 成人国产精品久久久| 欧美日韩国产中文字幕| 欧美精品在线免费播放| 欧洲精品在线视频| 久久视频这里只有精品| 2019最新中文字幕| 国产精品91久久| 欧美精品久久一区二区| 91在线高清免费观看| 欧美激情在线有限公司| 亚洲国产日韩精品在线| 日韩视频在线免费| 久久精品这里热有精品| 精品无人国产偷自产在线| 欧美激情中文字幕乱码免费| 亚洲综合在线中文字幕| 不卡伊人av在线播放| 91麻豆国产精品| 亚洲综合大片69999| 日韩毛片在线观看| 国产91色在线|免| 国产精品v片在线观看不卡| 国产成人精品一区二区三区| 亚洲精品自拍视频| 日韩电影大全免费观看2023年上| 日韩在线观看免费高清完整版| 91九色视频导航| 精品伊人久久97| 国产香蕉精品视频一区二区三区| 亚洲一区二区福利| 青草成人免费视频| 日韩av电影在线网| 亚洲娇小xxxx欧美娇小| 国产精品扒开腿做| 亚洲第一精品夜夜躁人人躁| 日韩成人高清在线| 成人黄色免费网站在线观看| 日本一区二三区好的精华液| 亚洲精品网站在线播放gif| 在线播放亚洲激情| 九九久久精品一区| 国产成人精品日本亚洲| 成人精品在线观看| 成人在线免费观看视视频| 日韩欧美国产视频| 国产日韩欧美夫妻视频在线观看| 亚洲国产欧美久久| 在线观看国产精品日韩av| 夜夜嗨av色综合久久久综合网| 视频在线一区二区| 91在线视频精品| 精品国内亚洲在观看18黄| 亚洲午夜av久久乱码| 欧美日韩免费网站| 97精品视频在线观看| 992tv在线成人免费观看| 亚洲视频专区在线| 人体精品一二三区| 亚洲国产成人爱av在线播放| 中文字幕精品久久久久| 日韩电影在线观看中文字幕| 欧美亚洲另类激情另类| xxav国产精品美女主播| 综合136福利视频在线| 日韩网站在线观看| 久久天天躁狠狠躁老女人| 亚洲美女自拍视频| 久久精品久久精品亚洲人| 国模吧一区二区三区| 国产高清在线不卡| 九色精品美女在线| 亚洲一区二区在线| 中文字幕久精品免费视频| 68精品久久久久久欧美| 91高清视频在线免费观看| 国产成人一区三区| 欧美激情亚洲激情| 91久热免费在线视频| 亚洲国产精品成人va在线观看| 成人精品一区二区三区电影免费| 中文字幕亚洲综合久久筱田步美| 91精品久久久久久久久久| 亚洲成人精品久久| 亚洲精品720p| 不卡毛片在线看| 国产精品偷伦免费视频观看的| 国产精品一区二区久久国产| 日本久久91av| 国产97在线亚洲| 91精品久久久久久久久久入口| 久久久久日韩精品久久久男男| 国产成人福利网站| 国产精品一区二区三区成人| 日韩精品在线第一页| 日韩欧美国产网站| 亚洲精品少妇网址| 久久久久久网址| 国产97免费视| 欧美与欧洲交xxxx免费观看| 亚洲最大的网站| 啊v视频在线一区二区三区| 亚洲成人久久一区| 国产精品久久久久久久久| 一区二区三区久久精品| 亚洲国产古装精品网站| 精品国产区一区二区三区在线观看| 日韩美女免费观看| 亚洲国产精久久久久久久| 久久亚洲一区二区三区四区五区高| 日韩在线资源网| 亚洲欧美综合另类中字| 国内精品一区二区三区| 国产大片精品免费永久看nba| 欧美亚洲另类制服自拍| 国内精品久久久久久影视8| 精品国产精品三级精品av网址| 激情懂色av一区av二区av| 日韩视频免费中文字幕| 国产一区二区三区免费视频| 精品久久在线播放| 久久久天堂国产精品女人| 久久影视三级福利片| 精品视频在线播放| 欧美日本中文字幕|