目录
1.信号灯集
1.1概念
信号灯(semaphore),也叫信号量。它是不同进程间或一个给定进程内部不同线程间同步的机制;System V信号灯集是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。而Posix信号灯指的是单个计数信号灯。
通过信号灯集实现共享内存的同步操作
1.2操作步骤
1.创建key值
2.创建或打开信号灯集
3.初始化信号灯集
4.pv操作
5.删除信号灯集
1.3函数接口
1.3.1创建或打开信号灯集
#include <sys/sem.h>int semget(key_t key, int nsems, int semflg);
功能:创建/打开信号灯
参数:
key:ftok产生的key值
nsems:信号灯集中包含的信号灯数目
semflg:信号灯集的访问权限,通常为IPC_CREAT |0666
返回值:
成功:信号灯集ID
失败:-1
出现这种情况就是semid等于0了我们可以手动去删除这个信号灯集:
ipcs -s :查看创建的信号灯集
ipcrm -s [semid]:删除信号灯集
示例:
#include <stdio.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <errno.h>
int main()
{
int semid;
key_y key;
key = ftok("./app", 'a');
if(key < 0)
{
perror("ftok err");
return -1;
}
semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0666);
if(semid < 0)
{
if(errno == EEXIST)
semid = semget(key, 2, 0666);
else
{
perror("semget err");
return -1;
}
}
printf("%d\n",semid);
return 0;
}
1.3.2初始化或删除信号灯集
int semctl ( int semid , int semnum , int cmd,… /*union semun arg*/ );功能:信号灯集合的控制(初始化/删除)
参数:
semid:信号灯集ID
semnum: 要操作的集合中的信号灯编号
cmd:
GETVAL:获取信号灯的值,返回值是获得值
SETVAL:设置信号灯的值,
IPC_RMID:从系统中删除信号灯集合
...:当cmd为SETVAL时,需要传递共用体
返回值:
成功 0
失败 -1
共用体格式:
union semun
{
int val; /* 信号量的初值 */
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) */
};
示例:
补充:
- 当cmd为SETVAL时需要传递第四个参数,类型为共用体,
用法:
union semun {
int val;
};
union semun sem;
sem.val = 10;
semctl(semid, 0, SETVAL, sem); //对编号为0的信号灯设置初值为10
1.当cmd为IPC_RMID时,表示删除信号灯集
用法:semctl(semid, 0, IPC_RMID) // 0:表示信号灯的编号,指定任意一个即可删除
2.当cmd为GETVAL时,表示获取信号灯的值
用法:printf("%d\n", semctl(semid, 0, GETVAL));
1.3.3 pv操作
int semop ( int semid , struct sembuf * opsptr , size_t nops );功能:对信号灯集合中的信号量进行PV操作
参数:
semid:信号灯集ID
opsptr:操作方式
nops: 要操作的信号灯的个数 1个
返回值:
成功 :0
失败:-1
struct sembuf {
short sem_num; // 要操作的信号灯的编号
short sem_op; // 0 : 等待,直到信号灯的值变成0
// 1 : 释放资源,V操作
// -1 : 分配资源,P操作
short sem_flg; // 0(阻塞),IPC_NOWAIT, SEM_UNDO
};
示例:
使用:
申请资源 P操作:
mysembuf.sem_num = 0;
mysembuf.sem_op = -1;
mysembuf.sem_flg = 0;
semop(semid, &mysembuf, 1);
释放资源 V操作:
mysembuf.sem_num = 0;
mysembuf.sem_op = 1;
mysembuf.sem_flg = 0;
semop(semid, &mysembuf, 1);
封装函数:使代码更简洁美观
示例:
1.4操作命令
ipcs -s :查看创建的信号灯集ipcrm -s [semid]:删除信号灯集