#include <sys/sem.h>
int main(void) {
// 创建新的或者获取已有的信号量集
/*
* semget 创建新的或者获取已有的信号量集
* key: ftok函数返回的key
* nsems int 信号量集中信号量个数
* semflg 标志位置
* */
// 操作信号量
/*
* semop 操作信号量
* semid int semget返回的信号量ID
* sops struct sembuf* 操作结构数组
* struct sembuf {
unsigned short sem_num; // 信号量在信号量集中的编号(编号从0开始)
short sem_op; // 操作数 3表示,释放资源3个,-2表示拿走资源2个
short sem_flg; // 操作标志 如果标志位包含 IPC_NOWAIT,在资源不够时不等待直接返回-1,errno设置为EAGAIN
};
* nsops unsigned int 操作结构数
* */
// 销毁信号量集
/*
* semctl
* semid int msgget获取的消息队列ID
* num int 需要操作的信号量编号(从0开始)
* cmd 要做的操作
* IPC_RMID 销毁共享内存
* GETALL 获取所有信号量的值 buf传入数组,通过buf获取所有值 例如: unsigned short values[4]
* SETALL 设置所有信号量的值 buf传入数组,通过buf设置所有值 例如: unsigned short values[4]={1,2,3,4}
* GETVAL 获取特定信号量的值
* SETVAL 设置特定信号量的值 buf传入int
*
* buf NULL
* 成功返回0 失败返回-1
* 注:在销毁时,如果有进程阻塞在semop函数,会立即返回-1,并且errno设置为ERMID
* */
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <sys/sem.h>
#define ARR_SIZE(arr) sizeof((arr))/sizeof((arr)[0])
const unsigned short BOOK_MAX_COUNT = 8;
typedef int(*Handler)(int, int, short);
typedef struct {
char name[128];
short count;
int index;
Handler handler;
} hbuf;
int handler(int semId, int index, short count) {
// 1. 表示未借书 2. 表示书已借完 0.表示正常 -1 表示其他错误
// 取出当前数值做判断
int value;
value = semctl(semId, index, GETVAL, NULL);
if (value == BOOK_MAX_COUNT && count > 0) {
return 1;
}
if (value == 0 && count < 0) {
return 2;
}
struct sembuf buf = {index, count, 0};
return semop(semId, &buf, 1);
}
// 判断字符串是否为数字
int isNumber(char *s) {
if (strspn(s, "1234567890") == strlen(s)) {
return 1;
} else {
return 0;
}
}
int main() {
// 初始化图书
char *books[5] = {"书本1", "书本2", "书本3", "书本4", "书本5"};
// 生成KEY
key_t key = ftok(".", 8);
printf("%d,生成key.\n", getpid());
// 创建信号量
printf("%d,创建信号量.\n", getpid());
int semID = semget(key, ARR_SIZE(books), IPC_CREAT | 0664);
if (semID == -1) {
perror("semget");
return -1;
}
char *js = "借";
char *hs = "还";
// 初始化操作
hbuf *handlers[ARR_SIZE(books) * 2] = {};
for (int i = 0; i < (ARR_SIZE(books)); i++) {
// 每本书有两个借还两个操作
// 0 1 2
// 0,1 2,3 4,5
hbuf *j = (hbuf *) malloc(sizeof(hbuf));
hbuf *h = (hbuf *) malloc(sizeof(hbuf));
strcat(j->name, js);
strcat(h->name, hs);
strcat(j->name, books[i]);
strcat(h->name, books[i]);
j->count = -1;
j->index = i;
j->handler = handler;
h->count = 1;
h->index = i;
h->handler = handler;
handlers[i * 2] = h;
handlers[i * 2 + 1] = j;
}
// 初始化信号量
unsigned short values[ARR_SIZE(books)] = {};
for (int i = 0; i < ARR_SIZE(books); i++) {
values[i] = BOOK_MAX_COUNT;
}
semctl(semID, 0, SETALL, values);
// 打印选项
char *cindex = malloc(sizeof(char) * 128);
int index;
for (;;) {
printf("==================\n");
// 获取所有信号集的数量
semctl(semID, 0, GETALL, values);
for (int i = 0; i < ARR_SIZE(handlers); i++) {
printf("%d.%s 剩余:%d\n", i, handlers[i]->name, values[handlers[i]->index]);
}
printf(">> ");
scanf("%s", cindex);
if (strcmp(cindex, "!") == 0) {
printf("结束\n");
break;
}
if (isNumber(cindex) == 0) {
printf("输入不合法\n");
continue;
}
index = atoi(cindex);
if (index >= ARR_SIZE(handlers)) {
printf("超长输入不合法\n");
continue;
}
int handler_val = handlers[index]->handler(semID, handlers[index]->index, handlers[index]->count);
if (handler_val == -1) {
perror("handlers");
return -1;
} else if (handler_val == 1) {
printf("未借书,不需要还书\n");
} else if (handler_val == 2) {
printf("书已借完,不能借书\n");
}
}
// 释放内存
printf("释放内存\n");
for (int i = 0; i < ARR_SIZE(handlers); i++) {
free(handlers[i]);
}
free(cindex);
// 释放信号量集
printf("释放信号量集\n");
semctl(semID, 0, IPC_RMID, NULL);
}