系统编程之信号量
1.信号量不同于while循环,while循环会占有cpu资源,而信号量则进入了休眠状态
2.信号量被删除后,所有等待信号量的资源的进程都将忽略等待继续运行,信号量只有一个但成员可以多个
如何使用信号量:
使用ipcs -s查看系统信号量
1.创建健值ftok()
2.创建信号量:功能 获取信号量的 ID
- 头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h> - 函数原型
int semget(key_t key, int nsems, int semflg);
参数 | 分析 |
---|---|
key | 信号量的键值 |
nsems | 信号量元素的个数 |
semflg | |
IPC_CREAT | 如果 key 对应的信号量不存在,则创建之 |
IPC_EXCL | 如果该 key 对应的信号量已存在,则报错 |
mode | 信号量的访问权限(八进制,如 0644) |
- 返回值
成功 该信号量的 ID
失败 -1
3.信号量初始化:
- 头文件
#include <sys/sem.h> - 函数原型
int semctl(int semid, int semnum, int cmd, ...);
参数 | 分析 |
---|---|
semid | 信号量 ID |
semnum | 信号量元素序号(数组下标) |
cmd | 操作的命令如下 |
IPC_STAT | 获取属性信息 |
IPC_SET | 设置属性信息 |
IPC_RMID | 立即删除该信号量,参数 semnum 将被忽略 |
IPC_INFO | 获得关于信号量的系统限制值信息 |
SEM_INFO | 获得系统为共享内存消耗的资源信息 |
SEM_STAT | 同 IPC_STAT,但 shmid 为该 SEM 在内核中记录所有 SEM 信息的数组的下标,因此通过迭代所有的下标可以获得系统中所有 SEM 的相关信息 |
GETALL | 返回所有信号量元素的值,参数 semnum 将被忽略 |
GETNCNT | 返回正阻塞在对该信号量元素 P 操作的进程总数 |
GETPID | 返回最后一个队该信号量元素操作的进程 PID |
GETVAL | 返回该信号量元素的值 |
GETZCNT | 返回正阻塞在对该信号量元素等零操作的进程总数 |
SETALL | 设置所有信号量元素的值,参数 semnum 将被忽略 |
SETVAL | 设置该信号量元素的值,赋予初始值等于第四个参数 |
第四个参数是一个联合体:
union semun {
int val; //SETVAL命令使用
struct semid_ds *buf; //IPC_STAT, IPC_SET 使用
unsigned short *array; //GETALL, SETALL 使用
struct seminfo *__buf; //IPC_INFO使用
};
使用 IPC_STAT 和 IPC_SET 需要用到以下属性信息结构体:
struct semid_ds
{
struct ipc_perm sem_perm; /* 权限相关信息 */
time_t sem_otime; /* 最后一次 semop( )的时间 */
time_t sem_ctime; /* 最后一次状态改变时间 */
unsigned short sem_nsems; /* 信号量元素个数 */
};
权限结构体如下:
struct ipc_perm
{
key_t __key;/* 该信号量的键值 key */
uid_t uid; /* 所有者有效 UID */
gid_t gid; /* 所有者有效 GID */
uid_t cuid; /* 创建者有效 UID */
gid_t cgid; /* 创建者有效 GID */
unsigned short mode; /* 读写权限 */
unsigned short __seq; /* 序列号 */
};
使用 IPC_INFO 时,需要提供以下结构体:
struct seminfo
{
int semmap; /* 当前系统信号量总数 */
int semmni; /* 系统信号量个数最大值 */
int semmns; /* 系统所有信号量元素总数最大值 */
int semmnu; /* 信号量操作撤销结构体个数最大值 */
int semmsl; /* 单个信号量中的信号量元素个数最大值 */
int semopm; /* 调用 semop( )时操作的信号量元素个数最大值 */
int semume; /* 单个进程对信号量执行连续撤销操作次数的最大值 */
int semusz; /* 撤销操作的结构体的尺寸 */
int semvmx; /* 信号量元素的值的最大值 */
int semaem; /* 撤销操作记录个数最大值 */
}
- 返回值
成功 | value |
---|---|
GETNCNT | semncnt |
GETPID | sempid |
GETVAL | semval |
GETZCNT | semzcnt |
IPC_INFO | 内核中记录所有 SEM 信息的数组的下标最大值 |
SEM_INFO | 同 IPC_INFO |
SEM_STAT | 内核中记录所有 SEM 信息的数组,下标为 semid 的信号量的 ID |
其他 | 0 |
失败 | -1 |
这里提供代码参考:example.c