1. 程式人生 > >System V 信號量使用相關函數

System V 信號量使用相關函數

mode 可選參數 訪問 訪問權限 給定 素數 per 分配 絕對值

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;
};

System V 信號量使用相關函數