信号量semaphore
信号量是一个计数器,用于为多个进程提供对共享数据对象的访问。常用的信号量形式为二元信号量(Binary semaphore)。它控制单个资源,初始值为1。但是,一般而言,信号量的初值可以是任意正数,该值表明有多少个共享资源单位可供共享应用。
数据结构
#include <sem.h>
struct ipc_perm
{
__kernel_key_t key;
__kernel_uid_t uid;
__kernel_gid_t gid;
__kernel_uid_t cuid;
__kernel_gid_t cgid;
__kernel_mode_t mode;
unsigned short seq;
};
/* Obsolete, used only for backwards compatibility and libc5 compiles */
struct semid_ds {
struct ipc_perm sem_perm; /* permissions .. see ipc.h */
__kernel_time_t sem_otime; /* last semop time */
__kernel_time_t sem_ctime; /* last change time */
struct sem *sem_base; /* ptr to first semaphore in array */
struct sem_queue *sem_pending; /* pending operations to be processed */
struct sem_queue **sem_pending_last; /* last pending operation */
struct sem_undo *undo; /* undo requests on this array */
unsigned short sem_nsems; /* no. of semaphores in array */
};
操作函数
1.创建和引用信号量
#include <sem.h>
int semget(key_t key, int nsems, int flag);
2.控制信号量
#include <sem.h>
int semctl(int semid, int semunm, int cmd, ...arg);
/* arg for semctl system calls. */
union semun {
int val; /* value for SETVAL */
struct semid_ds __user *buf; /* buffer for IPC_STAT & IPC_SET */
unsigned short __user *array; /* array for GETALL & SETALL */
struct seminfo __user *__buf; /* buffer for IPC_INFO */
void __user *__pad;
};
cmd参数:
IPC_STAT 对此集合去semid_ds结构,并存储在由arg.buf存储的结构中。
IPC_SET 按arg.buf指向的结构中的值,设置sem_perm.uid,sem_perm.gid和sem_perm.mode的值
IPC_RMID删除信号量的集合,该操作也是立即生效的。如果有其他进程正在使用这个信号量,则会返回EIDRM。
GETVAL返回semum的semval值
SETVAL设置semum的semval值
...
3.自动执行信号量集合上的操作数组
#include <sem.h>
int semop(int semid, struct sembuf semoparry[], size_t nops);
/* semop system calls takes an array of these. */
struct sembuf {
unsigned short sem_num; /* semaphore index in array */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
参数semoparray是一个指针,指向一个由sembuf结构表示的信号量操作数组。
sem_op值:
1.如果为正,对应进程释放占用的资源数,sem_op值加到信号量的值上
2.如果为负,对应要获取该信号量控制的资源数,信号量减去sem_op值
3.如果为0,这表示调用进程希望等待该信号量的值变成0
如果信号量的值小于sem_op的绝对值,即资源不能满足要求。
1.若指定IPC_NOWAIT,则semop()返回EAGAIN
2.若未指定IPC_NOWAIT,信号量的semncnt+1,调用进程被挂起直到信号量满足要求,或者系统中删除了此信号量,或者接受到了一个信号,从信号处理程序返回EINTR。
参考书目:《APUE》