程序間通訊 訊號量(P V操作)

2021-07-29 07:10:32 字數 3956 閱讀 6651

訊號量的基本介紹:

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

當請求⼀個使⽤訊號量來表⽰的資源時,程序需要先讀取訊號量的值來判斷資源是否可⽤。⼤於0,資源可以請求,等於0,⽆資源可⽤,程序會進⼊睡眠狀態直⾄資源可⽤。

當程序不再使⽤⼀個訊號量控制的共享資源時,訊號量的值+1,對訊號量的值進⾏的增減操作均為原⼦操作,這是由於訊號量主要的作⽤是維護資源的互斥或多程序的同步訪問。⽽在訊號量的建立及初始化上,不能保證操作均為原⼦性。

⼀ 為什麼要使⽤訊號量

為了防⽌出現因多個程式同時訪問⼀個共享資源⽽引發的⼀系列問題,我們需要⼀種⽅法,它可以通過⽣成並使⽤令牌來授權,在任⼀時刻只能有⼀個執⾏執行緒訪問**的臨界區域。

臨界區域是指執⾏資料更新的**需要獨佔式地執⾏。⽽訊號量就可以提供這樣的⼀種訪問機制,讓⼀個臨界區同⼀時間只有⼀個執行緒在訪問它, 也就是說訊號量是⽤來調協程序對共享資源的訪問的。其中共享記憶體的使⽤就要⽤到訊號量。

⼆ 訊號量的⼯作原理

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

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

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

linux提供了一些關與訊號量的操作的介面用於進行訊號量的建立、銷毀、p、v操作、初始化等操作 以下予以模擬實現訊號量的操作:

sem.h

#ifndef _tem_h_

#define _tem_h_

#include

#include

#include

#include

#include

#include

#define path "."

#define pid 0x66

int create_sem(int _semset_num);

int init_sem(int _sem_id);

int sem_p(int _sem_id,int _which);

int sem_v(int _sem_id,int _which);

int destroy_sem(int _sem_id);

int getsem();

#endif

sem.c

#include"tem.h"

static

int comm_sem(int _semset_num,int flag)

int semid = semget(key,_semset_num,flag);

if(semid<0)

return semid;

}int create_sem(int _semset_num)

int init_sem(int _sem_id)

; union semun _semun;

_semun.val = 1;

int ret = semctl(_sem_id,0,setval,_semun);

if (ret < 0)

return ret;

}int destroy_sem(int _sem_id)

return ret;

}int getsem()

static

int comm_op(int _sem_id,int which,int flag)

return ret;

}int sem_p(int sem_id,int which)

int sem_v(int sem_id,int which)

下面對linux提供的訊號量介面進行簡單介紹

#include 

#include

#include

int semget(key_t key, int nsems, int sem***);

semget

功能:建立乙個新的訊號量或獲取乙個已經存在的訊號量的鍵值。

返回值:成功返回訊號量的標識碼id。失敗返回-1;

引數:

key 為整型值,使用者可以自己設定。有兩種情況:

1. 鍵值是ipc_private,該值通常為0,意思就是建立乙個僅能被程序程序給我的訊號量。

2. 鍵值不是ipc_private,我們可以指定鍵值,例如1234;也可以乙個ftok()函式來取得乙個唯一的鍵值。

_nsems 表示初始化訊號量的個數。比如我們要建立乙個訊號量,則該值為1.,建立2個就是2。

_sem*** :訊號量的建立方式或許可權。有ipc_creat,ipc_excl。

ipc_creat如果訊號量不存在,則建立乙個訊號量,否則獲取。

ipc_excl只有訊號量不存在的時候,新的訊號量才建立,否則就產生錯誤。

semctl(int semid, int semnum, int cmd, …);

semctl() 在 semid 標識的訊號量集上,或者該集合的第 semnum 個訊號量上執⾏ cmd 指定的控制命令。 (訊號量集合索引起始於零。 )根據 cmd 不同,這個函式有三個或四個引數。當有四個引數時,第四個引數的型別是 union

。調⽤程式必須按照下⾯⽅式定義這個聯合體:

union semun ;

注意:該聯合體沒有定義在任何系統頭⽂件中,因此得⽤戶⾃⼰宣告。(centos下)

在這個函式中我們可以刪除訊號量或初始化訊號量。

功能:控制訊號量的資訊。

返回值:成功返回0,失敗返回-1;

引數:

_semid 訊號量的標誌碼(id),也就是semget()函式的返回值;

_semnum, 操作訊號在訊號集中的編號。從0開始。

_cmd 命令,表示要進行的操作。

引數cmd中可以使用的命令如下:

ipc_stat讀取乙個訊號量集的資料結構semid_ds,並將其儲存在semun中的buf引數中。

ipc_set設定訊號量集的資料結構semid_ds中的元素ipc_perm,其值取自semun中的buf引數。

ipc_rmid將訊號量集從記憶體中刪除。

getall用於讀取訊號量集中的所有訊號量的值。

getncnt返回正在等待資源的程序數目。

getpid返回最後乙個執行semop操作的程序的pid。

getval返回訊號量集中的乙個單個的訊號量的值。

getzcnt返回這在等待完全空閒的資源的程序數目。

setall設定訊號量集中的所有的訊號量的值。

setval設定訊號量集中的乙個單獨的訊號量的值。

int semop(int semid, struct sembuf *sops, unsigned nsops);

功能:使用者改變訊號量的值。也就是使用資源還是釋放資源使用權。

返回值:成功返回0,失敗返回-1;

引數:

_semid : 訊號量的標識碼。也就是semget()的返回值。

_sops是乙個指向結構體陣列的指標。

struct sembuf;

nsops:操作結構的數量,恆大於或等於1。

_sem***

sem_***可以設定為sem undo標識;sem_undo用於將修改的訊號量值在程序正常退出(呼叫exit退出或main執行完)或異常退出(如段異常、除0異常、收到kill訊號等)時歸還給訊號量。

如訊號量初始值是20,程序以sem_undo方式操作訊號量減2,減5,加1;在程序未退出時,訊號量變成20-2-5+1=14;在程序退出時,將修改的值歸還給訊號量,訊號量變成14+2+5-1=20。

程序間通訊 訊號量

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 ...