信号量是一个计数器。用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
特点:
1.信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
2.信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
3.每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
4.支持信号量组。
操作步骤:
1.获取信号量集
2.初始化信号量的值//有多少把钥匙
3.p and v 操作
4.粉碎信号量
一、获取信号量集
函数原型:
int semget(key_t key, int nsems, int semflg);
参数如下:
key = ftok(".",2);
nsems:有多少个信号,大于一则为信号量集;
semflg = IPC_CREAT||0666;//创建
若成功则返回信号量集的ID,否则返回-1;
二、初始化信号量的值
函数原型:
int semctl(int semid, int semnum, int cmd, …);
参数介绍:
semid:信号量集的ID
semnum:信号量集合里面的第几个信号量
cmd:需要用到的是SETVAL,如果第三个参数是SETVAL的话,那么就需要到第四个参数,union semun这个联合体的实例,下面看例子;
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) */
};
union semun initset;
initset.val = 1;//信号量(设置计数器值为1)
int judge = semctl(semid,0,SETVAL,initset);//操作数组的第0个信号量
if(judge == -1){//判断初始化是否成功
printf("initial semaphore failed\n");
}
三、p and v操作
需要用到的函数:
int semop(int semid, struct sembuf *sops, unsigned nsops);
p操作:sem_op > 0,信号量大于零,那么如果有进程正在休眠等待此信号量,则换行它们。
v操作:sem_op < 0,信号量小于零,请求 sem_op 的绝对值的资源
上栗子:
void pGetKey(int semid)//p操作
{
struct sembuf set;
set.sem_num = 0;
set.sem_op = -1;
set.sem_flg = SEM_UNDO;
semop(semid, &set ,1);
printf("get key\n");
}
void vReturnKey(int semid)//v操作
{
struct sembuf set;
set.sem_num = 0;
set.sem_op = -1;
set.sem_flg = SEM_UNDO;
semop(semid, &set ,1);
printf("get key\n");
}
四、粉碎信号量
int semctl(int semid, int semnum, int cmd);
还是用到这个函数,但是只用三个参数就可以;
semctl(semid, 0, IPC_RMID);
today is not easy,tomorrow will be more difficult,but the day after tomorrow will be wonderful!