訊號量主要用於程序間同步,避免併發訪問共享資源。
訊號量集合資料結構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操作。標頭檔案...