一、概念
二、特点
三、信号量数据结构
信号量具有自身特有的数据结构 semid_ds,该结构说明了信号量的一些状态信息等等,详细信息可参阅文件 /usr/include/linux/sem.h
。
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. semget
- 【头文件】:
#include <sys/types.h>
、#include <sys/ipc.h>
、#include <sys/sem.h>
- 【函数原型】:
int semget(key_t key, int nsems, int semflg);
- 【功能】:创建或访问一个信号量集
- 【参数】:
(1)key:信号量集的键值,由 ftok() 生成
(2)nsems:信号量集中信号量的个数
(3)semflg:权限标志位,由两部分组成,一部分为IPC对象存取权限(含义同 ipc_perm 中的 mode),另一部分为IPC对象创建模式标志(IPC_CREAT、IPC_EXCL),一般会将这两部分进行|
运算,从而完成对IPC对象创建的管理
- 【返回值】:成功返回一个信号量集标识符(非负整数);失败则返回 -1,并将 errno 设置为错误标识符
【示例】:演示 IPC_CREAT|IPC_EXCL
的使用效果
【代码】:
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
int main() {
extern int errno;
int semid = semget(0x123, 1, 0644|IPC_CREAT|IPC_EXCL);
if(semid == -1) {
printf("semget error!\n");
printf("errno: %d\n", errno);
perror("result");
return -1;
}
printf("semget success!\n");
return 0;
}
【执行结果】:
【分析】:
从执行结果来看,当我们第一次运行程序时,成功创建了信号量集。但是,当第二次运行程序后,发现创建失败,errno
被置为17,也就是 EEXIST
,错误信息为 File exists
,出现这样的结果是因为我们在第一次程序运行后,该信号量集就已经在系统中存在了,而我们在创建信号量集又使用了 IPC_EXCL
,这才导致 shmget
出错返回。
2. semctl
- 【头文件】:
#include <sys/types.h>
、#include <sys/ipc.h>
、#include <sys/sem.h>
- 【函数原型】:
int semctl(int semid, int semnum, int cmd, ...);
- 【功能】:获取或设置信号量集的有关信息
- 【参数】:
(1)semid:信号量集标识符
(2)semnum:当前信号量集中的哪一个信号量(下标从0开始)
(3)cmd:对信号量集要采取的动作
取值 说明 SETVAL
设置信号量集中信号量的计数值 GETVAL
获取信号量集中信号量的计数值 IPC_STAT
读取信号量集的 semid_ds 结构信息,并将其存储在第四个参数 buf 指定的地址空间中 IPC_SET
设置信号量集的 semid_ds 结构信息,这些取值来自于第四个参数 buf 指定地址空间中的参数(需要足够权限) IPC_RMID
删除信号量集 (4)… :这个参数取决于cmd
- 【返回值】:成功时具体的返回值依赖于cmd;失败则返回 -1,并将errno设置为错误标识符
【示例】:演示 IPC_STAT
的使用效果
【代码】:
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int main() {
int semid = semget(0x123, 1, 0644|IPC_CREAT);
if(semid == -1) {
printf("semget error!\n");
return -1;
}
struct semid_ds buf;
if(semctl(semid, 0, IPC_STAT, &buf) == -1) {
printf("semctl error!\n");
return -1;
}
printf("buf.sem_perm.mode = %o\n", buf.sem_perm.mode);
printf("buf.sem_perm.__key = %x\n", buf.sem_perm.__key);
return 0;
}
【执行结果】:
3. semop
- 【头文件】:
#include <sys/types.h>
、#include <sys/ipc.h>
、#include <sys/sem.h>
- 【函数原型】:
int semop(int semid, struct sembuf *sops, unsigned nsops);
- 【功能】:对信号量集中的信号量进行 PV 操作
- 【参数】:
(1)semid:信号量集标识符
(2)sops:指向存储信号操作结构的数组指针
(3)nsops:进行操作信号量的个数
- 【返回值】:成功时返回 0;失败则返回 -1,并将errno设置为错误标识符