两种实现的代码思路,第一种是将对商品和货架的两个操作定义为一个原子操作,然后生产者和消费者去分别实现不同的操作。另一种是把对商品和货架的操作定义为两个原子操作,但是要注意PV操作的顺序
计数信号量,一个原子操作
//计数信号量
#include <head.h>
int main(int argc, char **argv) {
int ret = 0;
//创建信号量
int semid = semget(3000, 2, IPC_CREAT|0666);
ERROR_CHECK(semid, -1, "semget");
//创建unsigned short数组来SETALL
unsigned short arr[2] = {0, 5};//商品0,5货架5
semctl(semid, 0, SETALL, arr); //0表示对全部信号量操作
//信号量的操作函数,数组一次实现两个原子操作
struct sembuf sop[2];
memset(sop, 0, sizeof(sop));
//父进程:生产者,生产商品,消耗货架
if(fork()){
sop[0].sem_num = 0; //对信号量0操作,即商品
sop[0].sem_op = 1; //生产商品
sop[0].sem_flg = 0;
sop[1].sem_num = 1; //对信号量1操作,即货架
sop[1].sem_op = -1; //消耗商品
sop[1].sem_flg = 0;
while(1){
//一个原子操作
ret = semop(semid, sop, 2);
ERROR_CHECK(ret, -1, "semop1");
//GETVAL直接返回信号代表的资源数量
printf("生产者:商品的数量 = %d, 货架的数量 = %d\n",
semctl(semid, 0, GETVAL), semctl(semid, 1, GETVAL));
sleep(1);
}
}
else{
//子进程:消费者,消耗商品,释放货架
sop[0].sem_num = 0;
sop[0].sem_op = -1;
sop[0].sem_flg = 0;
sop[1].sem_num = 1;
sop[1].sem_op = 1;
sop[1].sem_flg = 0;
while(1){
ret = semop(semid, sop, 2);
ERROR_CHECK(ret, -1, "semop2");
printf("消费者:商品的数量 = %d, 货架的数量 = %d\n", semctl(semid, 0, GETVAL), semctl(semid, 1, GETVAL));
sleep(2);
}
}
return 0;
}
两个原子操作,注意生产者和消费者的PV操作顺序
#include <func.h>
int main(int argc,char*argv[]) {
int ret = 0;
int semid = semget(9010, 2, IPC_CREAT | 0666);
unsigned short arr[2] = {5, 0};
semctl(semid, 0, SETALL, arr);
//两个原子操作,empty货架,full商品
struct sembuf empty[2], full[2];
memset(&full, 0, sizeof(full));
memset(&empty, 0, sizeof(empty));
//数组下标0代表生产者对empty的操作,下标1代表消费者对empty的操作
empty[0].sem_num = 0;
empty[0].sem_op = -1;
empty[0].sem_flg = 0;
empty[1].sem_num = 0;
empty[1].sem_op = 1;
empty[1].sem_flg = 0;
//数组下标0代表生产者对full的操作,下标1代表消费者对full的操作
full[0].sem_num = 1;
full[0].sem_op = 1;
full[0].sem_flg = 0;
full[1].sem_num = 1;
full[1].sem_op = -1;
full[1].sem_flg = 0;
//父进程:生产者,生产商品,消耗货架
if (fork()) {
while(1) {
ret = semop(semid, &empty[0], 1);
ERROR_CHECK(ret, -1, "semop1");
ret = semop(semid, &full[0], 1);
ERROR_CHECK(ret, -1, "semop2");
printf("生产者:商品的数量%d,货架的数量%d\n",
semctl(semid,1,GETVAL), semctl(semid,0,GETVAL));
sleep(1);
}
}
//子进程:消费者,生产商品,消耗货架
else {
while(1) {
ret = semop(semid, &full[1], 1);
ERROR_CHECK(ret, -1, "semop4");
ret = semop(semid, &empty[1], 1);
ERROR_CHECK(ret, -1, "semop3");
printf("消费者:商品的数量%d,货架的数量%d\n",
semctl(semid,1,GETVAL), semctl(semid,0,GETVAL));
sleep(3);
}
}
return 0;
}