c語言通過訊號量id獲取值 Linux訊號量

2021-10-13 18:13:13 字數 4145 閱讀 4003

@[toc]

訊號量(訊號燈)本質上是乙個計數器,用於協調多個程序(包括但不限於父子程序)對共享資料物件的讀/寫。它不以傳送資料為目的,主要是用來保護共享資源(訊號量、訊息佇列、socket連線等),保證共享資源在乙個時刻只有乙個程序獨享。

訊號量是乙個特殊的變數,只允許程序對它進行等待訊號和傳送訊號操作。最簡單的訊號量是取值0和1的二元訊號量,這是訊號量最常見的形式。

通用訊號量(可以取多個正整數值)和訊號量集方面的知識比較複雜,應用場景也比較少。

本文只介紹二元訊號量。

linux中提供了一組函式用於操作訊號量,程式中需要包含以下標頭檔案:

#include #include #include
semget函式用來獲取或建立訊號量,它的原型如下:

int semget(key_t key, int nsems, int sem***);
1)引數key是訊號量的鍵值,typedef unsigned int key_t,是訊號量在系統中的編號,不同訊號量的編號不能相同,這一點由程式設計師保證。key用十六進製制表示比較好。

2)引數nsems是建立訊號量集中訊號量的個數,該引數只在建立訊號量集時有效,這裡固定填1。

3)引數sem_flags是一組標誌,如果希望訊號量不存在時建立乙個新的訊號量,可以和值ipc_creat做按位或操作。如果沒有設定ipc_creat標誌並且訊號量不存在,就會返錯誤(errno的值為2,no such file or directory)。

4)如果semget函式成功,返回訊號量集的標識;失敗返回-1,錯誤原因存於error中。

示例:1)獲取鍵值為0x5000的訊號量,如果該訊號量不存在,就建立它,**如下:

int semid=semget(0x5000,1,0640|ipc_creat);
2)獲取鍵值為0x5000的訊號量,如果該訊號量不存在,返回-1,errno的值被設定為2,**如下:

int semid= semget(0x5000,1,0640);
該函式用來控制訊號量(常用於設定訊號量的初始值和銷毀訊號量),它的原型如下:

int semctl(int semid, int sem_num, int command, ...);
1)引數semid是由semget函式返回的訊號量標識。

2)引數sem_num是訊號量集陣列上的下標,表示某乙個訊號量,填0。

3)引數cmd是對訊號量操作的命令種類,常用的有以下兩個:

ipc_rmid:銷毀訊號量,不需要第四個引數;

setval:初始化訊號量的值(訊號量成功建立後,需要設定初始值),這個值由第四個引數決定。第四引數是乙個自定義的共同體,如下:

// 用於訊號燈操作的共同體。

union semun

;

4)如果semctl函式呼叫失敗返回-1;如果成功,返回值比較複雜,暫時不關心它。

示例:1)銷毀訊號量。

semctl(semid,0,ipc_rmid);
2)初始化訊號量的值為1,訊號量可用。

union semun sem_union;

sem_union.val = 1;

semctl(semid,0,setval,sem_union);

該函式有兩個功能:1)等待訊號量的值變為1,如果等待成功,立即把訊號量的值置為0,這個過程也稱之為等待鎖;2)把訊號量的值置為1,這個過程也稱之為釋放鎖。

int semop(int semid, struct sembuf *sops, unsigned nsops);
1)引數semid是由semget函式返回的訊號量標識。

2)引數nsops是操作訊號量的個數,即sops結構變數的個數,設定它的為1(只對乙個訊號量的操作)。

3)引數sops是乙個結構體,如下:

struct sembuf

;

示例:1)等待訊號量的值變為1,如果等待成功,立即把訊號量的值置為0;

struct sembuf sem_b;

sem_b.sem_num = 0;

sem_b.sem_op = -1;

sem_b.sem_*** = sem_undo;

semop(sem_id, &sem_b, 1);

2)把訊號量的值置為1。

struct sembuf sem_b;

sem_b.sem_num = 0;

sem_b.sem_op = 1;

sem_b.sem_*** = sem_undo;

semop(sem_id, &sem_b, 1);

為了便於理解,我把訊號量的操作封裝成csem類,稱之為訊號燈,類似互斥鎖,包括初始化訊號燈、等待訊號燈、掛出訊號燈和銷毀訊號燈。

/*

* 程式名:book259.cpp,此程式用於演示訊號量的使用方法。

*/#include #include #include #include #include #include class csem

; int sem_id; // 訊號燈描述符。

public:

bool init(key_t key); // 如果訊號燈已存在,獲取訊號燈;如果訊號燈不存在,則建立訊號燈並初始化。

bool wait(); // 等待訊號燈掛出。

bool post(); // 掛出訊號燈。

bool destroy(); // 銷毀訊號燈。

};int main(int argc, char *ar**)

printf("sem.init okn");

// 等待信訊號掛出,等待成功後,將持有鎖。

if (sem.wait()==false)

printf("sem.wait okn");

sleep(50); // 在sleep的過程中,執行其它的book259程式將等待鎖。

// 掛出訊號燈,釋放鎖。

if (sem.post()==false)

printf("sem.post okn");

// 銷毀訊號燈。

// if (sem.destroy()==false)

// printf("sem.destroy okn");

}bool csem::init(key_t key)

// 訊號燈建立成功後,還需要把它初始化成可用的狀態。

union semun sem_union;

sem_union.val = 1;

if (semctl(sem_id,0,setval,sem_union) < 0)

}else

} return true;

}bool csem::destroy()

return true;

}bool csem::wait()

return true;

}bool csem::post()

return true;

}

第一步:執行book259程式,它會建立鍵值為5000的訊號燈,並持有鎖,如下:

第二步:立即再執行乙個book259程式,它會獲取鍵值為5000的訊號燈,並等待鎖,如下:

第三步,當第一次執行的book259程式sleep完50秒之後,釋放鎖,第二個執行book259的程式將獲得鎖;

第四步,可以啟動更多的book259程式,它們將排隊等待鎖。

用ipcs -s 可以檢視系統的訊號量,內容有鍵值(key),訊號量編號(semid),建立者(owner),許可權(perms),訊號量數(nsems)。

用ipcrm -sem 訊號量編號,可以手工刪除訊號量,如下:

C語言筆記 訊號量sem t

includeint sem init sem t sem,int pshared,unsigned int value sem init 初始化乙個定位在 sem 的匿名信號量。value 引數指定訊號量的初始值。pshared 引數指明訊號量是由程序內線程共享,還是由程序之間共享。如果 psha...

訊號量和互斥量C語言示例理解執行緒同步

2.參考資料 了解執行緒訊號量的基礎知識,對深入理解python的執行緒會大有幫助。當兩個執行緒同時執行時,不可避免同時操作同乙個變數或者檔案等,所以需要有一組機制來確保他們能正確的執行 訊號量和互斥量。訊號量可以分為最簡單的 二進位制訊號量 和更通用的 計數訊號量 訊號量通常用來保護一段 使其每次...

哲學家就餐問題C語言實現(涉及多執行緒 訊號量等)

由dijkstra提出並解決的哲學家進餐問題 the dinning philosophers problem 是典型的同步問題。該問題是描述有五個哲學家共用一張圓桌,分別坐在周圍的五張椅子上,在圓桌上有五個碗和五隻筷子,他們的生活方式是交替地進行思考和進餐。平時,乙個哲學家進行思考,飢餓時便試圖取...