用共享内存和信号量去模拟一个卖火车票的程序。
首先建立一个共享内存和一个信号量,并初始化信号量,然后用一个指针指向共享内存。然后调用一个卖票的函数,去模拟卖票的功能。
头文件
#ifndef __SEMAPHORE_H__
#define __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 sem_init(int sem_id)
{
union semun sem;
sem.val = 1;
int ret = semctl(sem_id, 0, SETVAL, sem);
return ret;
}
//信号量的P操作
int sem_p(int sem_id)
{
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = -1;
sem.sem_flg = SEM_UNDO;
int ret = semop(sem_id, &sem, 1);
return ret;
}
//信号量的V操作
int sem_v(int sem_id)
{
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = 1;
sem.sem_flg = SEM_UNDO;
int ret = semop(sem_id, &sem, 1);
return ret;
}
//信号量的销毁
int sem_del(int sem_id)
{
int ret = semctl(sem_id, 0, IPC_RMID);
return ret;
}
#endif //__SEMAPHORE_H__
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/sem.h>
#include "semaphore.h"
typedef struct _shm
{
int flag;
int ticket;
}SHM;
void sell_ticket(SHM *pshm, int ret) //卖票函数
{
int time;
while(1)
{
time = rand() % 10 + 1;
usleep(time * 100000); //卖完一张票以后随机休眠0.几秒,模拟卖票窗口
sem_p (ret); //信号量的P操作,让一个卖票窗口进入内存去“取票”
if(pshm->ticket == 0) //票卖完,则退出程序
{
sem_v (ret);
break;
}
printf("卖掉一张票,座位号是:%d\n",pshm->ticket);
pshm->ticket--; //卖出一张票,总数减一
sem_v (ret); //信号量的V操作,让窗口重新去内存里去“取票”
}
printf("票已卖完\n");
}
int main(int argc, int **argv)
{
srand((unsigned)time(NULL)); //产生随机数
int shmid = shmget((key_t)1234, sizeof(SHM), 0666 | IPC_CREAT);
if(shmid == -1)
{
perror("shmget");
return -1;
}
int ret = semget((key_t)5678, 1, 0666 | IPC_CREAT); //创建共享内存
if(ret == -1)
{
perror("semget");
return -1;
}
SHM *pshm = shmat(shmid, NULL, 0); //映射到共享内存
if(pshm == (SHM *)-1)
{
perror("shmat");
return -1;
}
if(argc == 2) //初始化
{
pshm->ticket = 100;
sem_init(ret);
}
sell_ticket(pshm, ret); //开始卖票
if(argc == 2)
{
shmdt(pshm); //解除共享内存
shmctl(shmid, IPC_RMID, NULL); //删除共享内存
sem_del(ret); //删除信号量
}
return 0;
}