System V 信号量
在提到Posix 信号量時,指的是二值信号量或計數信号量,而System V信号量指的是入了計數信号量集
二值信号量:其值為0或1,類似于互斥鎖,資源被鎖住時為0,資源可用為1
計數信号量:其值在0和某個限制值之間的信号量,信号量的值就是可用資源數
計數信号量集:一個或多個信号量構成一個集合,集合中每個元素都是計數信号量(每個集合的信号量數存在一個限制)
semid_ds結構:
核心為每個信号量集維護的資訊結構
#include <sys/sem.h>
struct semid_ds{
struct ipc_perm sem_perm; // 目前信号量的通路權限
struct sem *sem_base; // 核心用于維護某個給定信号量的一組值的内部資料結構
ushort sem_nsems; // 集合中信号量的數目
time_t sem_otime; // 最近一次執行semop()的時間
time_t sem_ctime; // 集合建立時間或最近一次IPC_SET的時間
};
struct sem{
ushort_t semval; // 信号量實際值
short sempid; // 對信号量值執行最後一次操作的程序的程序ID
ushort_t semncnt; // 等待信号量值增長的程序數
ushort_t semzcnt; // 等待信号量值變為0的程序數
};
semget()函數:
#include <sys/sem.h>
// 建立一個信号量集或通路一個已存在的信号量集
// 成功傳回非負信号量辨別符,出錯傳回-1
int semget(key_t key, int nsems, int oflag);
// key: IPC 鍵
// nsems:指定集合中信号量數
// oflag:SEM_R(讀)和SEM_A(改)的組合,還可以按位與IPC_CREAT或IPC_CREAT|IPC_EXCL
semop()函數:
#include <sys/sem.h>
// 對信号量集中一個或多個信号量進行操作
// 成功傳回0,出錯傳回-1
int semop(int semid, struct sembuf *opsptr, size_t nops);
// semid:由semget()函數傳回的信号量辨別符
// nops: 指出opsptr指向的結構數組的元素數量
// opsptr:指向一個如下的數組
struct sembuf{
short sem_num; // 信号量集中信号量的索引值:0, 1, ... , nsems-1(sem_base[sem_num], 指定對某個特定信号量進行操作)
short sem_op; // 指定對特定信号量的操作
short sem_flg; // 操作标志,0, IPC_NOWAIT、SEM_UNDO
};
// sembuf結構内元素的排列順序并不保證如上述那樣,隻保證該結構中有上述三個元素
// sembuf結構不能靜态初始化(struct sembuf value = {0, 0, 0} // Error)
// sembuf結構需要運作時初始化(struct sembuf value; value.sem_num = 0; ...)
// sem_op:每個特定的操作有sem_op确定,它可以是負數、0、正數
// sem_op為正數時,其值加到semval(信号量目前值)上,對應于釋放信号量控制的資源
// 如果指定了SEM_UNDO标志,就從相應信号量的semadj(所指定信号量針對調用程序的調整值)減去sem_op
// sem_op為0,調用者等待semval變為0,如果semval已經為0,則立即傳回
// sem_op為負數,調用者希望等待semval變為大于或等于sem_op的絕對值,這對應于配置設定資源
semctl()函數:
#include <sys/sem.h>
// 對一個信号量執行各種控制操作
// 成功傳回非負值,出錯傳回-1
int semctl(int semid, int semnum, int cmd, ... /* union semun arg */);
// semid: 辨別其操作待控制的信号量集
// semnum: 辨別信号量集内的某個成員(sem_base[sem_num])
// cmd:可選值如下(除非另外說明,操作成功函數傳回值為0,出錯為-1)
// GETVAL:将semval的目前值作為函數傳回值傳回
// SETVAL:将semval設為arg.val(若操作成功,那麼相應信号量的semadj被設為0)
// GETPID:将sempid的目前值作為函數傳回值傳回
// GETNCNT:将semncnt(等待semval變為大于其目前值的線程數)的目前值作為函數傳回值傳回
// GETZCNT:将semzcnt(等待semval變為0的線程數)的目前值作為函數傳回值傳回
// GETALL:傳回指定信号量集内每個成員的semval值(這些值通過arg.array指針傳回)
// SETALL:設定指定信号量集内每個成員的semval值(這些值通過arg.array指針傳遞)
// IPC_RMID:将由semid指定的信号量集從系統删除
// IPC_SET:設定指定信号量集的semid_ds結構中的sem_perm.uid、sem_perm.gid、sem_perm.mode,這些值由arg.buf參數指向的結構中的相應成員指定
// IPC_STAT:傳回指定信号量集目前的semid_ds結構(通過arg.buf)
// arg: 可選參數,根據 cmd 參數而定
union semun{
int val;
struct semid_ds *buf;
ushort *array;
};
轉載于:https://www.cnblogs.com/lnlin/p/9741943.html