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

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

進程間通信之信號量

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

信號量(semaphore)與已經介紹過的ipC機構(管道、FIFO以及消息隊列)不同。它是一個計數器,用于多進程對共享數據對象的訪問。

為了獲得共享資源,進程需要執行下列操作:

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

(2)若此信號量的值為正,則進程可以使用該資源。進程將信號量值減1,表示它使用了一個資源單位。

(3)若此信號量的值為0,則進程進入休眠狀態,直至信號量值大于0.進程被喚醒后,它返回至第(1)步。

當進程不再使用由一個信號量控制的共享資源時,該信號量值增1。如果有進程正在休眠等待此信號量,則喚醒它們。

為了正確地實現信號量,信號量值的測試及減1操作應當是原子操作。為此,信號量通常是在內核中實現的。

常用的信號量形式被稱為二元信號量或雙態信號量(binary semaphore)。它控制單個資源,初始值為1。但是一般而言,信號量的初值可以是任一正值,該值說明有多少個共享資源單位可供共享應用。

遺憾的是,XSI的信號量與此相比要復雜得多。三種特性造成了這種不必要的復雜性:

(1)信號量并非是單個非負值,而必需將信號量定義為含有一個或多個信號量值的集合。當創建一個信號量時,要指定該集合中信號量值的數量。

(2)創建信號量(semget)與對其賦初值(semctl)分開。這是一個致命的弱點,因為不能原子地創建一個信號量集合,并且對該集合中的各個信號量值賦初值。

(3)即使沒有進程正在使用各種形式的XSI IPC,它們仍然是存在的。有些程序在終止時并沒有釋放已經分配給它的信號量,所以我們不得不為這種程序擔心。下面將要說明的undo功能就是假定要處理這種情況的。

內核為每個信號量集合設置了一個semid_ds結構:

struct semid_ds {    struct ipc_perm    sem_perm;        unsigned short     sem_nsems;    /* # of semaphores in set */    time_t             sem_otime;    /* last-semop() time */    time_t             sem_ctime;    /* last-change time */    ...};

Single UNIX Specification定義了上面所示的各字段,但是具體實現可在semid_ds結構中定義添加的成員。

每個信號量由一個無名結構表示,它至少包含下列成員:

struct {    unsigned short    semval;     /* semaphore value, always >= 0 */    pid_t             sempid;     /* pid for last Operation */    unsigned short    semncnt;    /* # PRocesses awaiting semval>curval */    unsigned short    semzcnt;    /* # processes awaiting semval==0 */};

要獲得一個信號量ID,要調用的第一個函數是semget。

#include <sys/sem.h>int semget(key_t key, int nsems, int flag);返回值:若成功則返回信號量ID,若出錯則返回-1

http://www.CUOXin.com/nufangrensheng/p/3561681.html中標識符與鍵部分,說明了將key轉換為標識符的規則,討論了是否創建一個新集合,或是引用一個現存的集合。

nsems是該集合中的信號量數。如果是創建新集合(一般在服務器進程中),則必須指定nsems。如果引用一個現存的集合(一個客戶進程),則將nsems指定為0。

創建一個新集合時,對semid_ds結構的下列成員賦初值:

  • ipc_perm結構按http://www.CUOXin.com/nufangrensheng/p/3561681.html中權限結構所述進行初始化。該結構中mode成員按flag中的相應權限位設置。這些權限用http://www.CUOXin.com/nufangrensheng/p/3561681.html表15-2中的常量指定。
  • sem_otime設置為0.
  • sem_ctime設置為當前時間。
  • sem_nsems設置為nsems。

semctl函數包含了多種信號量操作。

#include < sys/sem.h>int semctl(int semid, int semnum, int cmd, ... /* union semun arg */);返回值:見下

注意,依賴于所請求的命令,第四個參數是可選的,如果使用該參數,則其類型是semun,它是多個特定命令參數的聯合(union):

union semun {    int                 val;      /* for SETVAL */    struct semid_ds    *buf;      /* for IPC_STAT and IPC_SET */    unsigned short     *array;    /* for GETALL and SETALL */};

注意,這是一個聯合,而非指向聯合的指針。

cmd參數指定下列10種命令中的一種,在semid指定的信號量集合上執行此命令。其中有5條命令(如下綠色背景所示)是針對一個特定的信號量值的,它們用semnum指定該信號量集合中的一個成員。semnum值在0和nsems-1之間(包括0和nsems-1)。

IPC_STAT 對此集合取semid_ds結構,并存放在由arg.buf指向的結構中。

IPC_SET 按由arg.buf指向結構中的值設置與此集合相關結構中的下列三個字段值:sem_perm.uid、sem_perm.gid和sem_perm.mode。此命令只能由下列兩種進程執行:一種是其有效用戶ID等于sem_perm.cuid或sem_perm.uid的進程;另一種是具有超級用戶特權的進程。

IPC_RMID 從系統中刪除該信號量集合。這種刪除是立即發生的。仍在使用此信號量集合的其他進程在它們下次試圖對此信號量集合進行操作時,將出錯返回EIDRM。此命令只能由下列兩種進程執行:一種是其有效用戶ID等于sem_perm.cuid或sem_perm.uid的進程;另一種是具有超級用戶特權的進程。

GETVAL 返回成員semnum的semval值。

SETVAL 設置成員semnum的semval值。該值由arg.val指定。

GETPID 返回成員semnum的sempid值。

GETNCNT 返回成員semnum的semncnt值。

GETZCNT 返回成員semnum的semzcnt值。

GETALL 取該集合中所有信號量的值,并將它們存放在由arg.array指向的數組中。

SETALL 按arg.array指向的數組中的值,設置該集合中所有信號量的值。

對于除GETALL以外的所有GET命令,semctl函數都返回相應的值。其他命令的返回值為0.

函數semop自動執行信號量集合上的操作數組,這是個原子操作。

#include <sys/sem.h>int semop(int semid, struct sembuf semoparray[], size_t nops);返回值:若成功則返回0,若出錯則返回-1

參數semoparray是一個指針,它指向一個信號量操作數組,信號量操作由sembuf結構表示:

struct sembuf {    unsigned short    sem_num;         /* member # in set ( 0, 1, ..., nsems-1) */    short             sem_op;          /* operation (negtive, 0, or positive) */    short             sem_flag;        /* IPC_NOWAIT, SEM_UNDO */};

參數nops規定該數組中操作的數量(元素數)。

對集合中每個成員的操作由相應的sem_op值規定。此值可以是負值、0或正值。

(1)最易于處理的情況是sem_op為正。這對應于進程釋放占用的資源數。sem_op值加到信號量的值上。如果指定了undo標志(此標志對應于相應sem_flag成員的SEM_UNDO位),則也從該進程的此信號量調整值中減去sem_op。

(2)若sem_op為負,則表示要獲取由該信號量控制的資源。

如若該信號量的值大于或等于sem_op的絕對值(具有所需的資源),則從信號量值中減去sem_op的絕對值。這保證信號量的結果值大于或等于0。如果指定了undo標志,則sem_op的絕對值也加到該進程的此信號量調整值上。

如果信號量值小于sem_op的絕對值(資源不能滿足要求),則:

(a)若指定了IPC_NOWAIT,則semop出錯返回EAGAIN。

(b)若未指定IPC_NOWAIT,則該信號量的semncnt值加1(因為調用進程將進入休眠狀態),然后調用進程被掛起直至下列事件之一發生:

(i)此信號量變成大于或等于sem_op的絕對值(即某個進程已釋放了某些資源)。此信號量的semncnt減1(因為已經結束等待),并且從信號量值中減去sem_op的絕對值。如果指定了undo標志,則sem_op的絕對值也加到該進程的此信號量調整值上。

(ii)從系統中刪除了此信號量。在此情況下,函數出錯則返回EIDRM。

(iii)進程捕捉到一個信號,并從信號處理程序返回。在此情況下,此信號量的semncnt值減1(因為調用進程不再等待),并且函數出錯返回EINTR。

(3)若sem_op為0,這表示調用進程希望等待到該信號量值變成0。

如果信號量值當前是0,則此函數立即返回。

如果信號量值非0,則:

(a)若指定了IPC_NOWAIT,則出錯返回EAGAIN。

(b)若未指定IPC_NOWAIT,則該信號量的semzcnt值加1(因為調用進程將進入休眠狀態),然后調用進程被掛起,直至下列事件之一發生為止:

(i)此信號量值變成0。此信號量的semzcnt值減1(因為調用進程已經結束等待)。

(ii)從系統中刪除了此信號量。在此情況下,函數出錯返回EIDRM。

(iii)進程捕捉到一個信號,并從信號處理程序返回。在此情況下此信號量的semzcnt值減1(因為調用進程不再等待),并且函數出錯返回EINTR。

semop函數具有原子性,它或者執行數組中的所有操作,或者什么也不做。

exit時信號量調整

正如前面提到的,如果在進程終止時,它占用了經由信號量分配的資源,那么就會成為一個問題。無論何時,只要為信號量操作指定了SEM_UNDO標志,然后分配資源(sem_op值小于0),那么內核就會記住對于該特定信號量,分配給調用進程多少資源(sem_op的絕對值)。當該進程終止時,不論自愿或者不自愿,內核都將檢驗該進程是否還有尚未處理的信號量調整值,如果有,則按調整值對相應信號量值進行處理。

如果用帶有SETVAL或SETALL命令的semctl設置一信號量的值,則在所有進程中,對于該信號量的調整值都設置為0。

實例:信號量與記錄鎖的耗時比較

如果多個進程共享一個資源,則可使用信號量或記錄鎖。

若使用信號量,則先創建一個包含一個成員的信號量集合,然后對該信號量值賦初值1。為了分配資源,以sem_op為-1調用semop;為了釋放資源,則以sem_op為+1調用semop。對每個操作都指定SEM_UNDO,以處理在未釋放資源條件下進程終止的情況。

若使用記錄鎖,則先創建一個空文件,并且用該文件的第一個字節(無需存在)作為鎖字節。為了分配資源,先對該字節獲得一個寫鎖;釋放該資源時,則對該字節解鎖。記錄鎖的性質確保了當一個鎖的屬主進程終止時,內核會自動釋放該鎖。

在linux上,記錄鎖與信號量鎖相比,在時間上要多耗時約60%。

雖然記錄鎖慢于信號量鎖,但如果只需要鎖一個資源(例如共享存儲段)并且不需要使用XSI信號量的所有花哨的功能,則寧可使用記錄鎖。理由是使用簡易,且進程終止時系統會處理任何遺留下來的鎖。

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


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91精品国产91| 黄色精品在线看| 久久福利视频导航| 久久久久久久久久久网站| 国产精品揄拍500视频| 欧美一区二区色| 日本一区二三区好的精华液| 亚洲精品中文字幕有码专区| 久久久精品电影| 秋霞午夜一区二区| 日韩欧美a级成人黄色| 精品久久久久久久大神国产| 国产一区二区三区视频免费| 精品国产依人香蕉在线精品| 欧美日韩亚洲天堂| 精品久久久久国产| 午夜精品久久久99热福利| 一区二区三区在线播放欧美| 九九热这里只有精品免费看| 亚洲激情国产精品| 国产视频精品一区二区三区| 亚洲人成77777在线观看网| 亚洲毛片一区二区| 日韩中文字幕国产| 欧美激情性做爰免费视频| 亚洲网站在线观看| 国产精品日日摸夜夜添夜夜av| 成人亚洲欧美一区二区三区| 中文字幕日韩高清| 亚洲成**性毛茸茸| 国产精品男人爽免费视频1| 疯狂做受xxxx高潮欧美日本| 欧美影院在线播放| 国产精品电影久久久久电影网| 欧美在线影院在线视频| 精品国产区一区二区三区在线观看| 91欧美精品午夜性色福利在线| 亚洲国产精品电影在线观看| 在线观看国产精品91| 久久久久久国产精品美女| 日韩福利视频在线观看| 欧美人交a欧美精品| 欧美日韩成人免费| 欧美多人爱爱视频网站| 日韩成人av一区| 一本大道亚洲视频| 欧美电影免费看| 欧美激情视频在线| 日韩精品视频观看| xvideos成人免费中文版| 日韩av免费在线| 欧美精品少妇videofree| 欧美精品福利在线| 久久久久国产精品免费网站| 国外日韩电影在线观看| 久久伊人精品视频| 91九色国产在线| 国产精品96久久久久久| 狠狠综合久久av一区二区小说| 精品无人区太爽高潮在线播放| 91精品国产乱码久久久久久久久| 欧美黑人xxxx| 欧美另类老肥妇| 精品中文字幕在线观看| 韩国福利视频一区| 亚洲一区二区免费在线| 久久久精品国产网站| 国产美女久久精品香蕉69| 国产精品丝袜一区二区三区| 九九热视频这里只有精品| 91久久精品美女| 日韩美女在线播放| 黄色一区二区三区| 中文字幕国产亚洲2019| 欧美日韩第一视频| 欧美日韩国产精品一区二区三区四区| 成人免费视频97| 中文字幕亚洲欧美日韩2019| 高清一区二区三区日本久| 91美女高潮出水| 欧美激情欧美激情在线五月| 91地址最新发布| 久久亚洲精品中文字幕冲田杏梨| 亚洲精美色品网站| xxx欧美精品| 92看片淫黄大片看国产片| 亚洲午夜未删减在线观看| 亚洲精品第一国产综合精品| 91国内产香蕉| 中文一区二区视频| 国产精品偷伦免费视频观看的| 大桥未久av一区二区三区| 欧美黄色性视频| 九九热在线精品视频| 亚洲国产日韩欧美在线动漫| 国产成人福利网站| 在线视频亚洲欧美| 中文字幕在线视频日韩| 91精品国产91久久久久久吃药| 亚洲区中文字幕| 亚洲第一网站男人都懂| 中文字幕一区电影| 欧美日韩国产第一页| 狠狠躁18三区二区一区| 青草青草久热精品视频在线观看| 国产精品免费一区| 中文字幕一区日韩电影| 日韩精品小视频| 欧美成人免费全部观看天天性色| 国产视频精品自拍| 国产精品美女午夜av| 欧美激情第1页| 国产精品一区二区久久| 久久69精品久久久久久久电影好| 成人精品在线视频| 欧美日韩免费看| 综合欧美国产视频二区| 国产午夜精品全部视频播放| 日韩成人av在线播放| 欧美日韩国产影院| 久久久久久久久国产| 国产精品美女久久久免费| 97视频在线观看成人| 日韩中文字幕欧美| 欧美精品videos另类日本| 国产精品一区二区性色av| 亚洲日韩欧美视频一区| 最近2019中文字幕大全第二页| 亚洲缚视频在线观看| 国产精品嫩草视频| 2019最新中文字幕| 欧美精品免费看| 欧美性xxxxxx| 成人啪啪免费看| 欧美高清在线观看| 日本精品免费一区二区三区| 成人欧美在线视频| 国产精品视频区| 国产精品777| 欧美日韩中文字幕在线视频| 福利一区福利二区微拍刺激| 久久久久久成人精品| 日韩美女福利视频| 国产aⅴ夜夜欢一区二区三区| 亚洲美女视频网站| 91理论片午午论夜理片久久| 日韩中文理论片| 欧美日韩中国免费专区在线看| 国产亚洲精品美女久久久| 北条麻妃一区二区三区中文字幕| 中文字幕日韩精品在线| 综合网中文字幕| 91在线视频九色| 日韩在线视频一区| 久久久久国产精品www| 国产一区二区丝袜| 日韩精品福利网站| 日本精品中文字幕| 日本国产欧美一区二区三区| 一个人看的www久久| 亚洲最新视频在线| 成人免费网站在线| 91美女片黄在线观| 秋霞午夜一区二区|