信号量
介绍
- 信号量本质是一个计数器,用来统计临界资源数量的一个计数器,根据临界资源的数量,同步和互斥进程使用的临界资源。
- 信号量主要用来起到同步互斥的目的,和共享内存配合在进程间实现互斥的传输数据
- 信号量不仅可以用来在不同进程间的同步和互斥,还可以在线程间实现同步和互斥
函数
1. semget()
int semget (key_t __key, int __nsems, int __semflg)
- 函数说明
- key: 该值得获取通过 ftok 函数
- nsems:初始信号集合中的数组个数,如果是新建的必须指定该值,如果引用已有的信号量,则置为 0
- flag:设置的权限,参考消息队列
2. semctl()
semctl (int __semid, int __semnum, int __cmd, .../*union semun arg*/)
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) */
};
- 函数说明
- semid: 信号 ID,从 semget() 函数中返回的
- semnum: 指定信号量集合中的哪一个成员, 从 0 到 nsems-1
- cmd: ctl的一些控制命令,具体使用 man semctl 查看
- arg:可选参数,具体使用取决于所请求的命令
- 成功返回 0,失败返回 -1
1. semop()
int semop (int __semid, struct sembuf *__sops, size_t __nsops);
struct sembuf
{
unsigned short int sem_num; /* semaphore number */
short int sem_op; /* semaphore operation */
short int sem_flg; /* operation flag */
};
- 函数说明
- semid: 信号量 ID
- sops: 一个指向 sembuf 结构的指针
- nops: 规定该数组中操作数的数量
- 返回值:成功返回0,失败返回 -1
代码
// semaphore.h
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/sem.h>
#include<cstdio>
union semun
{
int val;
semid_ds *buf;
unsigned short* array;
};
int set_semvalue(int sem_id, int count);
void del_semvalue(int sem_id);
int semaphore_p(int sem_id);
int semaphore_v(int sem_id);
// semaphore.cpp
#include"semaphore.h"
// init semaphore
int set_semvalue(int sem_id, int count){
semun sem_union;
sem_union.val = count;
if(semctl(sem_id, 0, SETVAL, sem_union) == -1){
printf("set_semvalue failed\n");
return -1;
}
return 0;
}
void del_semvalue(int sem_id){
semun sem_union;
if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1) {
printf("del_semvalue failed\n");
}
}
int semaphore_p(int sem_id){
sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id, &sem_b, 1) == -1){
printf("semphore_p failed\n");
return -1;
}
return 0;
}
int semaphore_v(int sem_id){
sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id, &sem_b, 1) == -1) {
printf("semaphore_v failed\n");
return -1;
}
return 0;
}
// sem_1.cpp
#include"semaphore.h"
int main()
{
key_t key = ftok("./tmp",2);
int sem_id = semget(key, 1, 0666 | IPC_CREAT);
set_semvalue(sem_id,0);
for(int i = 0; i < 10; ++i){
semaphore_p(sem_id);
printf("sem1 semaphore_p: %d\n",i);
}
printf("%d -- finished\n", getpid());
del_semvalue(sem_id);
return 0;
}
// sem_2.cpp
#include"semaphore.h"
/*
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) */
};
*/
int main()
{
key_t key = ftok("./tmp",2);
int sem_id = semget(key, 1, 0666 | IPC_CREAT);
for(int i = 0; i < 10; ++i){
printf("sem2 semaphore_v i:%d\n",i);
semaphore_v(sem_id);
sleep(1);
}
printf("%d -- finished\n",getpid());
return 0;
}