先前介紹的POSIX信號量概念:
- 二值信號量:0,1
- 計數信號量:0和某個限制值之間的信號量。
System V 中信號量:
計數信號量集:一個或多個信號量,其中每個都是計數信號量。
對於系統的每個信號量集,內核維護一個信息結構:<sys/sem.h>中定義
/* Data structure describing a set of semaphores. */
struct semid_ds
{
struct ipc_perm sem_perm; /* operation permission struct */
__time_t sem_otime; /* last semop() time */
__syscall_ulong_t __glibc_reserved1;
__time_t sem_ctime; /* last time changed by semctl() */
__syscall_ulong_t __glibc_reserved2;
__syscall_ulong_t sem_nsems; /* number of semaphores in set */
__syscall_ulong_t __glibc_reserved3;
__syscall_ulong_t __glibc_reserved4;
};
semget、semop、semctl
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
// 返回:若成功返回非負標識符,出錯爲-1
int semop(int semid, struct sembuf *sops, size_t nsops);
// 返回:若成功返回0,出錯爲-1
int semtimedop(int semid, struct sembuf *sops, size_t nsops, const struct timespec *timeout);
int semctl(int semid, int semnum, int cmd, ...);
// 返回:成功返回非負值,出錯-1
semget 函數:創建一個信號量集,或者訪問一個已存在的信號量集。
- 返回值:一個稱爲信號量標識符的整數。
- nsems參數:指定集合中的信號量數。若不創建,只訪問一個信號量集,可以設置爲0。一旦創建,就不能改變其中的信號量數。
- semflg:SEM_R 和SEM_A的組合。R表示read。A表示alter。還可以與IPC_CREAT、IPC_EXCL按位與。
當創建一個信號量集時,semid_ds結構中的以下成員被初始化:
- sem_perm 結構中的uid 和 cuid 成員被置爲調用進程的有效用戶ID,gid 和 cgid 成員被置爲調用進程的有效組ID。
- semflg參數中的讀寫權限位存入sem_perm.mode。
- sem_otime被置爲0,sem_ctime則被置爲當前時間。
- sem_nsems被置爲nsems參數的值。
- 與該集合中每個信號量關聯的各個sem結構並不初始化。這些結構是在以SET_VAL或SETALL命令調用semctl時初始化的。
semop 函數:打開後,對其中一個或者多個信號量的操作。
其中sembuf結構:
/* Structure used for argument to `semop' to describe operations. */
struct sembuf
{
unsigned short int sem_num; /* semaphore number (0,1,...,nsems-1) */
short int sem_op; /* semaphore operation */
short int sem_flg; /* operation flag ( 0, IPC_NOWAIT, SEM_UNDO ) */
};
/* Flags for `semop'. */
#define SEM_UNDO 0x1000 /* undo the operation on exit */
sem_op:正數,0,負數
semctl 函數:對一個信號量執行各種控制操作。
semnum參數:信號量成員。僅僅用於GETVAL、SETVAL、GETNCNT、GETZCNT、GETPID命令。
第四個參數是可選的,取決於第三個參數cmd。
注意:這個聯合需要應用自己定義,它是按值傳遞的,不是按引用傳遞的。
/* Commands for `semctl'. */
#define GETPID 11 /* get sempid */
#define GETVAL 12 /* get semval */
#define GETALL 13 /* get all semval's */
#define GETNCNT 14 /* get semncnt */
#define GETZCNT 15 /* get semzcnt */
#define SETVAL 16 /* set semval */
#define SETALL 17 /* set all semval's */
/* Control commands for `msgctl', `semctl', and `shmctl'. */
#define IPC_RMID 0 /* Remove identifier. */
#define IPC_SET 1 /* Set `ipc_perm' options. */
#define IPC_STAT 2 /* Get `ipc_perm' options. */
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
};
struct seminfo
{
int semmap;
int semmni;
int semmns;
int semmnu;
int semmsl;
int semopm;
int semume;
int semusz;
int semvmx;
int semaem;
};
GETVAL ---把semval的當前值作爲函數返回值返回。既然信號量絕不會是負數(semval被聲明成一個整數unsigned short),那麼成功的返回值總是非負數。
SETVAL ---把semval值設置成爲arg.val。如果操作成功,那麼相應信號量在所有進程中的信號量調整值(semadj)將被置爲0。
GETPID ---把sempid的當前值作爲函數返回值返回。
GETNCNT---把semncnt的當前值作爲函數返回值返回。
GETZCNT---把semzcnt的當前值作爲函數返回值返回。
GETALL----返回所指定信號量集內每個成員的semval值。這些值通過arg.array指針返回,函數本身的返回值則爲0。注意,調用者必須分配一個unsigned short整數數組,該數組要足夠容納所指定信號量集內所有成員的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參數指向的結構中的相應成員。semid_ds結構中的sem_ctime成員也被設置成當前時間。
IPC_STAT--(通過arg.buf參數)返回所指定信號量集當前的semid_ds結構。注意,調用者必須首先分配一個semid_ds結構,並把arg.buf設置成指向這個結構。
信號量限制: