linux下信號量及其SEM_UNDO標誌


AT&T的貝爾實驗室,對Unix早期的進程間通信進行了改進和擴充,形成了"system V IPC",其通信進程主要侷限在單個計算機內。IPC對象指的是共享內存(share memory)、消息隊列(message queue)和信號燈集(semaphore)。

信號燈(semaphore),也叫信號量

本質;一種數據操作鎖(本身是一個計數器,是對臨界資源的保護),它本身不具有數據交換的功能,而是通過控制其他的通信資源(文件,外部設備)來實現進程間通信,它本身只是一種外部資源的標識。信號量在此過程中負責數據操作的互斥、同步等功能。

 當請求一個使用信號量來表示的資源時,進程需要先讀取信號量的值來判斷資源是否可用。大於0,資源可以請求,等於0,無資源可用,進程會進入睡眠狀態直至資源可用。當一個進程不再使用一個信號量控制的共享資源時,信號量的值+1,對信號量的值進行的增減操作爲原子操作,這是由於信號量主要的作用是維護資源的互斥或多進程的同步訪問。而信號量的創建以及初始化上,不能保證操作爲原子操作。

 

使用信號量的原因:爲了防止出現因多個程序同時訪問一個共享資源而引發的一系列問題,它可以通過生成並使用令牌來授權,在任意時刻只能有一個執行線程訪問代碼的臨界區域。臨界區域是指執行數據更新的代碼需要獨佔式地執行。而信號量就可以提供這樣的一種訪問機制,讓一個臨界區同一時間只有一個線程在訪問它,也就是說信號量是用來協調進程對共享資源的訪問的。

缺點:創建和初始化分離。

信號燈是不同進程間或一個給定進程內部不同線程間同步的機制。System V的信號燈是一個或者多個信號燈的一個集合。其中的每一個都是單獨的計數信號燈。System V 信號燈由內核維護。主要函數semget,semop,semctl。


1、semget函數創建一個信號量集對象(得到一個信號量集標識符)

    函數原型:int semget(key_t key,int nsems,int semflg)

    key:由ftok()函數的得到

    nsems:創建信號量集中信號的個數

    semflg:

        IPC_CREAT:若內核中不存在鍵值與key相等的信號量集,則創建,否則,返回此信號量集的標識符

        IPC_EXCL:單獨使用無意義

        IPC_CREAT | IPC_EXCL :創建一個新的信號量集並返回信號量集的標識符,否則,返回-1.

    返回值:成功返回信號量集的標識符。失敗返回-1.

 

2、semctl函數:在指定的信號集或信號集內的某個信號上執行操作控制

    函數原型:int semctl(int semid,int semnum,int cmd,union semun arg)

      semid: 信號量集標識符

      semnum:信號量集數組上的下標,表示某一個信號量

      arg:

                union semun {

                   short val;          /*SETVAL用的值*/

                   struct semid_ds* buf; /*IPC_STATIPC_SET用的semid_ds結構*/

                   unsigned short* array; /*SETALLGETALL用的數組值*/

                   struct seminfo *buf;   /*爲控制IPC_INFO提供的緩存*/

                  } arg;

3、semop函數:對信號量進行P,V操作(本文的重點) 

P操作負責把當前進程由運行狀態轉換爲阻塞狀態,直到另外一個進程喚醒它。操作爲:申請一個空閒資源(把信號量減1),若成功,則退出;若失敗,則該進程被阻塞;

V操作負責把一個被阻塞的進程喚醒,它有一個參數表,存放着等待被喚醒的進程信息。操作爲:釋放一個被佔用的資源(把信號量加1),如果發現有被阻塞的進程,則選擇一個喚醒之。

semop函數原型如下:

int semop(int semid, struct sembuf  *sops, unsigned nsops);

semop操作中:sembuf結構的sem_flg成員可以爲0IPC_NOWAITSEM_UNDO 。爲SEM_UNDO時,它將使操作系統跟蹤當前進程對這個信號量的修改情況,如果這個進程在沒有釋放該信號量的情況下終止,操作系統將自動釋放該進程持有的。

sembuf結構的sem_flg成員爲SEM_UNDO時,它將使操作系統跟蹤當前進程對這個信號量的修改情況,如果這個進程在沒有釋放該信號量的情況下終止,操作系統將自動釋放該進程持有的信號量,從而使另外一個進程可以繼續工作,防止其他進程因爲得不到信號量而發生【死鎖現象】。爲此一般建議使用SEM_UNDO。

測試代碼:

sem.h

wKioL1eTcqSxR0NoAAB3ZBA4OxA801.png-wh_50

sem.c

wKioL1eTcyrhkLR7AABogO2O3hk363.png-wh_50

wKiom1eTcyqD4Lw0AABe270bJ6U000.png-wh_50

wKiom1eTcyvAlnf-AABgNhHVxWs835.png-wh_50

    semtest.c

wKioL1eTcyvgMbXHAABT8YfEGhE369.png-wh_50

wKiom1eTcyyhOCOkAAA9nTYAIKw397.png-wh_50

    運行結果:

wKioL1eTcyyyYC_1AAA2v98qPkI917.png-wh_50


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章