#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/*
* key:返回的 ID 与 key 有关系
* nsems:信号量的值
* semflg:创建标记
* return:成功返回信号量 ID,失败返回 -1,并设置 erron
*/
int semget(key_t key, int nsems, int semflg);
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/*
* semid:信号量 ID
* sops:对信号量的操作
* nsops:要操作的信号数量
* return:成功返回 0,失败返回 -1,并设置 erron
*/
int semop(int semid, struct sembuf *sops, size_t nsops);
struct sembuf {
/* 信号量的个数,除非使用多个信号量,否则设置为 0 */
unsigned short sem_num;
/* 信号量的操作,-1 表示 p 操作,1 表示 v 操作 */
short sem_op;
/* 通常设置为 SEM_UNDO,使得 OS 能够跟踪信号量并在没有释放时自动释放 */
short sem_flg;
};
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/*
* semid:要设置的信号量 ID
* semnum:要设置的信号量的个数
* cmd:设置的属性
*/
int semctl(int semid, int semnum, int cmd, ...);
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
};
// 创建或获取一个信号量
int sem_get(int sem_key) {
int sem_id = semget(sem_key, 1, IPC_CREAT | 0666);
if (sem_id == -1) {
printf("sem get failed.\n");
exit(-1);
} else {
printf("sem_id = %d\n", sem_id);
return sem_id;
}
}
// 初始化信号量
int set_sem(int sem_id) {
union semun sem_union;
sem_union.val = 1;
if(semctl(sem_id, 0, SETVAL, sem_union) == -1) {
fprintf(stderr, "Failed to set sem\n");
return 0;
}
return 1;
}
void del_sem(int sem_id) {
union semun sem_union;
if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
fprintf(stderr, "Failed to delete sem, sem has been del.\n");
}
// 减 1,加锁,P 操作
void sem_down(int sem_id) {
if (-1 == semop(sem_id, &sem_lock, 1))
fprintf(stderr, "semaphore lock failed.\n");
}
// 加 1,解锁,V 操作
void sem_up(int sem_id) {
if (-1 == semop(sem_id, &sem_unlock, 1))
fprintf(stderr, "semaphore unlock failed.\n");
}
int main(int argc, char **argv) {
int sem_id = sem_get(12);
// 第一次调用多加一个参数,第二次调用不加参数,仅在第一次调用时创建信号量
if (argc > 1 && (!set_sem(sem_id))) {
printf("set sem failed.\n");
return -1;
}
// P 操作
sem_down(sem_id);
printf("sem lock...\n");
printf("do something...\n");
sleep(10);
// V 操作
sem_up(sem_id);
printf("sem unlock...\n");
// 第二次调用后删除信号量
if (argc == 1)
del_sem(sem_id);
return 0;
}