天天看點

System V 信号量使用相關函數

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