程序間通訊之訊號量

2021-08-20 03:39:50 字數 3744 閱讀 5329

訊號量主要用於程序間同步,避免併發訪問共享資源。

訊號量集合資料結構struct semid_ds:在此資料結構中定義了整個訊號量集合的基本屬性,如訪問許可權。

訊號量資料結構struct sem:訊號量集合使用指標指向乙個由陣列組成的訊號量單元,在此訊號量單元中儲存了各訊號量的值。

它們的定義:

訊號量集合資料結構:

struct semid_ds
每個訊號量結構:

struct sem
訊號量使用步驟:

1、建立訊號量或獲得在系統已存在的訊號量,此時需要呼叫semget()函式。不同的程序通過使用同乙個訊號量鍵值來獲得同乙個訊號量。

2、初始化訊號量,此時使用semctl()函式的setval操作,當使用二維訊號量時,通常將訊號量初始化為1。

3、進行訊號量的pv操作,此時呼叫semop()函式。這一步是實現程序之間的同步和互斥的核心工作部分。

4、如果不需要訊號量,則從系統中刪除它,此時使用semctl()函式的ipc_rmid操作。此時需要注意,在程式中不應該出現對已經被刪除的訊號量的操作。

訊號量/訊號量集合操作:

1、semget()函式建立訊號量集合:

原型:int semget(key_t key,int nsems,int sem***)

引數:1)key:訊號量的鍵值,多個程序可以通過訪問同乙個訊號量,其中有個特殊的鍵值ipc_private。它用於建立當前程序的私有資料訊號量。

2)nsems:需要建立的訊號量數目,通常取值為1。

3)sem***:同open()函式的許可權位。其中使用ipc_creat標誌建立新的訊號量,訊號量已經存在也不報錯。同時使用ipc_excl建立乙個新的唯一的訊號量,若訊號量已存在則返回出錯。

2、semctl()函式控制訊號量或訊號量集合:

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

引數:1)semid:semget()函式返回的訊號量集識別符號。

2)semnum:訊號量在訊號集中的編號,操作訊號量集時,此引數無意義。單個訊號量中取為0。單個訊號量也即只用乙個訊號量的訊號量集。

3)cmd:對訊號量集或訊號量集中某些訊號量的操作方式。

如果操作訊號量集,cmd可取ipc_rmid、ipc_set、ipc_stat和ipc_info、getall、setall等。

含義(同msgctl的相關操作):

ipc_stat:獲取訊號量集的semid_ds結構,並存放在由第四個引數arg的buf指向的semid_ds結構中。semid_ds是在系統中描述訊號量集的資料結構。

ipc_rmid:從系統中刪除訊號量集。

如操作單個訊號量,cmd可取ipc_setval、ipc_getval等。

含義:ipc_setval:將訊號量值設定為arg的val值

ipc_getval:返回訊號量的當前值

4)arg:是union semun結構,該結構可能在某些系統中並不給出定義,此時必須由程式設計師自己定義。

union semun

關於semctl()函式,更詳細的資訊請man一下semctl,使用這個函式很簡單的,只是內容有點多而已。

3、semop()函式:

多個程序中使用此函式修改同乙個訊號量集合中的各個訊號量的值(在原訊號量值的基礎上進行加/減,即訊號量的pv操作,注意pv操作都是原子操作),各程序根據獲取的訊號量值來決定自己的行為,實現程序間通訊。

原型:int semop(int semid,struct sembuf *sops,size_t nsops)

引數:nsops:運算元組sops(第二個引數)中的操作個數(元素數目),通常取值為1(乙個操作)

sops:指向訊號量的運算元組,乙個操作包括以下成員:

struct sembuf

成員含義:

1)sem_num:要操作的訊號量在訊號量集合中的編號。

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

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

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

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

使用示例:(假設訊號量集中的各訊號量的值已經初始化)

struct sembuf sops[4];

sops[0].sem_num = 1;

sops[0].sem_op = -1;

sops[0].sem_*** = 0;

sops[1].sem_num = 2;

sops[1].sem_op = 3;

sops[1].sem_*** = 0;

semop(mysemid,sops,2);

呼叫了semop後,上面的**進行了這樣的操作:

第乙個sop即sops[0],用於操作訊號集中的第二個訊號量(sem_num=1),對其訊號量進行減1操作(sem_op=-1)。

第二個sop即sops[1],用於操作訊號集中的第三個訊號量(sem_num=2),對其訊號量進行加3操作(sem_op=3)。

訊號量實現生產消費模型:

這裡用的不是二元訊號量,不是用訊號量來實現互斥訪問其他資源。這裡用了兩個訊號量,乙個訊號量的值表示產品數,乙個訊號量的值表示倉庫空間。消費者和生產者都能修改這兩個值,生產者每生產乙個產品,產品數加1,倉庫空間減1,消費者每消費乙個產品,產品數減1,空間倉庫空間加1。重點是訊號量的pv操作。

sem_productor.c:

#include#include#include#include#include#include#includeint 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; //identify the space

arg.array = sem_array;

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

if(ret == -1)

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();

}

sem_customer.c:

#include#include#include#include#include#include#includeint sem_id;

void init()

int main(int argc,char *argv)

}

程序間通訊之訊號量

訊號量的本質是一種資料操作鎖,其本身不具有資料交換的能力,而是通過控制其他的通訊資源 檔案 外部裝置 來實現程序間通訊,它本身只是一種外部資源的標識。訊號量在此過程中負責資料的互斥 同步等功能。當請求乙個訊號量來表示資源時,程序需要讀取訊號量的值來判斷資源是否可用。大於0,資源可以請求,等於0,無資...

程序間通訊之訊號量

訊號量的本質是一種資料操控鎖,它本身不具有資料交換的功能,而是通過來控制其他的通訊資源來實現程序間通訊的,訊號主要負責資料的同步與互斥功能。程序請求乙個使用訊號量來表示的資源時,首先要讀取訊號量的值來判斷資源是否能被使用,若訊號量的值大於0,資源可用,等於0,無資源可用,同時程序會進入睡眠狀態,直到...

程序間通訊之 訊號量

訊號量相當於記錄資源能同時被多少個程序訪問。訊號量的作用 程序間同步控制。訊號量有乙個初值,每當有程序申請使用訊號量,就會通過乙個p操作對訊號量進行 1操作,當計數器減到0的時候就說明沒有資源了,其他程序要想訪問就必須等待,當該程序執行完這段工作之後,就會執行v操作,即對訊號量進行 1操作。標頭檔案...