Linux程序間通訊(3) 訊號量

2021-08-02 09:05:06 字數 3583 閱讀 7045

訊號量的本質是一種資料操作鎖,它本身不具有資料交換的功能,而是通過控制其他的通訊資源(檔案,外部裝置)來實現程序間通訊,它本身只是一種外部資源的標識。訊號量在此過程中負責資料操作的互斥、同步等功能。

為了防止出現因多個程式同時訪問乙個共享資源而引發的一系列問題,我們需要一種方法,它可以通過生成並使用令牌來授權,在任一時刻只能有乙個執行執行緒訪問**的臨界區域。臨界區域是指執行資料更新的**需要獨佔式地執行。而訊號量就可以提供這樣的一種訪問機制,讓乙個臨界區同一時間只有乙個執行緒在訪問它,也就是說訊號量是用來調協程序對共享資源的訪問的。

訊號量是乙個特殊的變數,程式對其訪問都是原子操作,且只允許對它進行等待(即p(訊號變數))和傳送(即v(訊號變數))資訊操作。最簡單的訊號量是只能取0和1的變數,這也是訊號量最常見的一種形式,叫做二進位制訊號量。而可以取多個正整數的訊號量被稱為通用訊號量。而在訊號量的建立及其初始化上,不能保證操作均為原子性。

由於訊號量只能進行兩種操作等待和傳送訊號,即p(sv)和v(sv),他們的行為是這樣的:

p(sv):如果sv的值大於零,就給它減1;如果它的值為零,就掛起該程序的執行

v(sv):如果有其他程序因等待sv而被掛起,就讓它恢復執行,如果沒有程序因等待sv而掛起,就給它加1.

舉個例子,就是兩個程序共享訊號量sv,一旦其中乙個程序執行了p(sv)操作,它將得到訊號量,並可以進入臨界區,使sv減1。而第二個程序將被阻止進入臨界區,因為當它試圖執行p(sv)時,sv為0,它會被掛起以等待第乙個程序離開臨界區域並執行v(sv)釋放訊號量,這時第二個程序就可以恢復執行。

建立/獲取訊號量

#include 

int semget(key_t key, int num_sems, int sem_flags);

key:非0整數,不相關的程序可以通過它訪問乙個訊號量(一般由ftok函式產生)

num_sems: 指定需要的訊號量數目,一般是1。

sem_flags:是一組標誌,當想要當訊號量不存在時建立乙個新的訊號量,可以和值ipc_creat做按位或操作。設定了ipc_creat標誌後,即使給出的鍵是乙個已有訊號量的鍵,也不會產生錯誤。而ipc_creat | ipc_excl則可以建立乙個新的,唯一的訊號量,如果訊號量已存在,返回乙個錯誤。

改變訊號量的值

#include 

int semop(int sem_id, struct sembuf *sem_opa,size_t num_sem_ops);

sem_id: 是semget函式返回的訊號量識別符號

sembuf結構體:

struct sembuf;

num_sem_ops: 設定的訊號量值

控制訊號量

#include 

int semctl(int sem_id, int sem_num, int command,...);

sem_id: semget 返回的訊號量識別符號

sem_num: 設定訊號量值

command : 一般為setval 或者 ipc_rmid

setval:用來把訊號量初始化為乙個已知的值。p 這個值通過union semun中的val成員設定,其作用是在訊號量第一次使用前對它進行設定。

ipc_rmid:用於刪除乙個已經無需繼續使用的訊號量識別符號。

如果有第四個引數,一般為union senum 結構體

union semun;

#include#include#include#include#include#include#define pathname "."

#define proj_id 6666

union semno

;int createsemset(int nums);

int getsemset();

int initsemset(int semid, int nums);

int p(int semid);

int v(int semid);

int destorysemset(int semid);

/******************************************/

int commsemset(int flags, int nums)

int semid = semget(_k, nums, flags);

if(semid < 0)

return semid;

}/******************************************/

/******************************************/

int createsemset(int nums)

/******************************************/

/******************************************/

int getsemset()

/******************************************/

/******************************************/

int initsemset(int semid,int nums)

return0;}

/******************************************/

/******************************************/

int commpv(int semid ,int nums, int flags)

return0;}

/******************************************/

/******************************************/

int p(int semid)

/******************************************/

/******************************************/

int v(int semid)

/******************************************/

/******************************************/

int destorysemset(int semid)

return0;}

/******************************************/

int main()

}else

}destorysemset(semid);

}

編譯

gcc -o  comm

comm.c

結果:

Linux程序間通訊 3 訊號量

unix網路程式設計 卷2 程序間通訊 第2版 中文版 同步與互斥 臨界資源 訊號量是用來解決程序間的同步與互斥問題的一種程序間通訊機制。pv操作 實現步驟 建立訊號量或獲得在系統中已經存在的訊號量,此時需要呼叫semget 函式。不同程序通過使用同乙個訊號量鍵值來獲得同乙個訊號量 初始化訊號量,此...

程序間通訊 3 訊號量

目錄 1.前言 2.訊號量 3.訊號量集結構 4.建立訊號量semget 5.改變訊號量值semop 6.控制訊號量semctrl 本文章中所有例子,基於rhel6.5。訊號量是一種用於提供不同程序間或乙個程序間的不同執行緒間進行同步手段的原語,system v訊號量在核心中維護。二值訊號量 其值只...

linux 訊號量(程序間通訊)

將使用乙個程式來演示訊號量的使用,程式用pv操作控制訊號量,以操作臨界區,p操作讓訊號量減1,v操作讓訊號量加1,而pv操作之間的 即為臨界區關鍵 每次只能由乙個程序訪問。程式建立出乙個子程序,在兩個程序中分別有一段臨界區關鍵 實現的功能都是不斷的順序輸出0 9的字元。保證程序間同步 plain v...