程序間通訊 訊號量

2021-06-27 18:57:36 字數 4629 閱讀 6173

訊號量與已經介紹過的ipc機構(管道、fifo以及訊息列隊)不同。它是乙個計數器,用於多程序對共享資料物件的訪問。為了獲得共享資源,程序需要執行下列操作:

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

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

(3) 若此訊號量的值為0,則程序進入睡眠狀態,直至訊號量值大於0。若程序被喚醒後,它返回至(第( 1 )步)。

通常所說的建立乙個訊號量實際上是建立乙個訊號量集合,在這個訊號量集合中,可能有多個訊號量。整個訊號量集合由以下部分組成:

(1)訊號量集合資料結構:在此資料結構中定義了整個訊號量集合的基本屬性,如訪問許可權、指標、最近修改的時間和佇列中訊號量佇列資訊。

struct semid_ds ;
(2)訊號量:訊號量集合使用指標指向乙個由陣列組成的訊號量單元,在此訊號量單元中儲存了建立時申請的訊號量,每個訊號量的資料結構中的成員變數主要為該訊號量的當前值。

在使用訊號量之前,首先需要建立乙個訊號量集合,該訊號量集合中可以包含多個訊號量。建立乙個訊號量集合的函式semget:

#include int semget(key_t  key, int  nsems, int  flag) ;

//返回:若成功則返回訊號量id,若出錯則為- 1

第乙個引數key_t型別的key值,一般由ftok函式產生。

第二個引數_nsems為建立的訊號量個數,各訊號量以陣列的方式儲存。這個陣列用於初始化陣列物件。

第三個引數_sem***用來標識訊號量集合的許可權,如0770為檔案訪問許可權型別。這些值可以與基本許可權以或的方式一起使用。

在linux作業系統中,可使用semctl函式對乙個訊號量集合以及訊號量集合中的訊號量進行操作。

#include int semctl(ints  emid, int  semnum, int  cmd, union  semunarg);
第乙個引數_semid為要操作的訊號量集合識別符號,該值一般由semget函式返回。

第二個引數為集合中訊號量的編號。如果標識某個訊號量,此值為該訊號量的下標(從0到n-1);如果標識整個訊號量集合,則設定為0.

第三個引數cmd引數指定下列十種命令中的一種,使其在semid指定的訊號量集合上執行此命令。其中有五條命令是針對乙個特定的訊號量值的,它們用semnum指定該集合中的乙個成員。semnum值在0和nsems-1之間(包括0和nsems-1)。

(1)ipc_stat 對此集合取semidds結構,並存放在由arg.buf指向的結構中。

(2)ipc_set 按由arg.buf指向的結構中的值設定與此集合相關結構中的下列三個字段值:semperm.uid, semperm.gid和semperm.mode。此命令只能由下列兩種程序執行:一種是其有效使用者i d等於semperm.cuid或semperm.uid的程序;另一種是具有超級使用者特權的程序。

(3)ipc_rmid 從系統中刪除該訊號量集合。這種刪除是立即的。仍在使用此訊號量的其他程序在它們下次意圖對此訊號量進行操作時,將出錯返回eidrm。此命令只能由下列兩種程序執行:一種是具有效使用者id等於semperm.cuid或semperm.uid的程序;另一種是具有超級使用者特權的程序。

(4)getval 返回成員semnum的semval值。

(5)setval 設定成員semnum的semval值。該值由arg.val指定。

(6)getpid 返回成員semnum的sempid值。

(7)getncnt 返回成員semnum的semncnt值。

(8)getzcnt 返回成員semnum的semzcnt值。

(9)getall 取該集合中所有訊號量的值,並將它們存放在由arg.array指向的陣列中。

(10)setall 按arg.array指向的陣列中的值設定該集合中所有訊號量的值。

對於除了getall以外的所有get命令,semctl函式都返回相應值。其他命令的返回值為0。

第四個引數是可選,是否使用取決於所請求的命令,如果使用該引數,則其型別是semum,它是多個命令特定引數的聯合:

union semun  ;
(1)如果操作為setval,則第四個引數為val,是相應訊號量的值。

(2)如果操作為ipc_stat&ipc_set,則第四個引數為struct semid_ds結構體變數。

(3)如果操作為getall&setall,則第四個引數為陣列位址。

(4)如果操作為ipc_info,則第四個引數為struct seminfo結構體變數。

除了可以使用semctl系統呼叫訪問訊號量外,還可以通過semo系統呼叫來操作單個訊號量:

#include int semop(int  semid, struct  sembufs  emoparray, size_t  nops) ;

//返回:若成功則為0,若出錯則為-1

第乙個引數為要操作的訊號量集合識別符號,該值一般由semget函式返回。

第二個引數為struct sembuf結構的變數,其定義如下:

struct sembuf  ;
此結構體有3個成員變數:

(1)semnum為操作的訊號量編號。

(2)sem_op為作用於訊號量的操作:該值如果為正整數標識增加訊號量的值(如果是1,表示在原來的基礎上加1,如果為3,表示在原來的基礎上加3),如果為負整數表示減小訊號量的值,如果為0表示訊號量的當前值進行是否為0的測試。

(3)sem_***為操作標識,可選以下各值:

ipc_nowait:在對訊號量集合的操作不能執行的情況下,呼叫立即返回,對某訊號量操作,即使其中乙個操作失敗,也不會導致修改集合中的其他訊號量。

sem_undo:當程序退出後,該程序對sem進行的操作將被撤銷。

第三個引數nops規定該陣列中操作的數量(元素數)。

生產消費問題是乙個經典的數學問題,要求生產者--消費者在固定的倉庫條件下,生產者每生產乙個產品將占用乙個倉庫空間,生產者生產的產品庫存不能越過倉庫的儲存量,消費者每消費乙個產品將增加乙個倉庫空間,消費者在倉庫產品為0時不能再消費。

本例中採用訊號量來解決問題。為了便於理解,本例中使用了兩個訊號量,乙個用來管理消費者(以下為sem_produce),乙個用來管理生產者(以下為sem_custom),即sem_produce表示當前倉庫可用的空間的數量,sem_custom用來表示當前倉庫中產品的數量。

(1)對於生產者來說:其需要申請的資源為倉庫中的剩餘空間,因此,生產者在生產乙個產品前需申請sem_produce訊號量。當此訊號量大於0,即有可用空間,將生產產品,並將sen_produce的值減去1(因為占用了乙個空間);同時,當其生產了乙個產品後,當前倉庫的產品數量增加1,需要將sem_custom訊號量自動加1.

(2)對於消費者來說:其需要申請的資源為倉庫中的產品,因此,消費者在消費乙個產品前將申請sem_custom訊號量。當此訊號量的值大於0時,即有可用產品,將消費乙個產品,並將sem_custom訊號量的值減去(因為消費了乙個產品);同時,當消費了乙個產品,當倉庫的剩餘空間增加1,需要將sem_produce訊號量自動加1.

這兩個訊號量被生產者-消費者影響,從而保證生產的最大化,並保證生產的產品有可儲存的倉庫空間。

生產者:

#include #include #include #include #include int sem_id;

void init()

arg;

key = ftok(".",'s');

sem_id = semget(key, 2, ipc_creat|0644);

sem_array[0] = 0; //identify the productor

sem_array[1] = 100; //idnetify the space

arg.array = sem_array;

ret = semctl(sem_id, 0, setall, arg); //初始化

if (ret == -1)

printf("setall failed (%d)\n", errno);

printf("productor init is %d\n", semctl(sem_id, 0, getval)); //列印初始化結果,產品數

printf("space init is %d\n\n",semctl(sem_id, 1, getval)); //空間數

}void del()

int main(int argc, char *argv)

del();

}

消費者:

#include #include #include #include int sem_id;

void init()

int main(int argc, char *argv)

}

程序間通訊 訊號量

ipc識別符號和關鍵字 在終端輸入ipcs,可以看到目前系統中所有的ipc資訊 第一列的key就是ipc的關鍵字,第二列是ipc的識別符號。ftok 函式用於獲得乙個ipc的關鍵字,其函式原型是 key t ftok const char pathname,int proj id 下面是乙個訊號量的...

程序間通訊 訊號量

system ipc中,對於每乙個新建的訊號量 訊息佇列 共享記憶體,都有乙個在整個系統中唯一的識別符號。每個標識也都有唯一對應的關鍵字,關鍵字的資料型別為ket t 在終端輸入命令 ipcs 可以看到目前系統中所有的ipc資訊 共享記憶體段 鍵 shmid 擁有者 許可權 位元組 nattch 狀...

程序間通訊 訊號量

訊號量不是ipc 機構,它只是乙個計數器用於不同程序之間或同一程序不同執行緒之間的同步,型別 二元訊號 值為0或 1,1說明有可用資源,0說明此時資源占用,其他程序需等待。計數訊號量 表示可用資源數量。計數訊號量集 由乙個或多個訊號量組成的集合,每乙個都是計數訊號量。訊號量資料結構 include ...