加入信号量的简易卖票系统

首先,我们在一般的基础上,不同进程访问同一内存,即共享内存的前提上加入信号量,两者比对看,前者可能售卖同一张票,即两个进程同时访问共享内存,加入信号量就是为了杜绝这种情况的发生,因为信号量就是为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行进程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个进程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。下面是两者的代码

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
#include <time.h>

typedef struct _shm
{
	int flag;
	int ticket;
}SHM;

int sellTicket(SHM* pshm)
{
	while(1)
	{
		int time =rand()%10 + 1;
		usleep(time*100000);
		if(pshm->flag == 1)
		{
			pshm->flag = 0;
			if(pshm->ticket == 0)
			{
				pshm->flag = 1;
				break;
			}
			printf("卖掉一张票,座位号:%d\n",pshm->ticket);
			pshm->ticket--;
			pshm->flag =1;
		}
	}
}
int main(int argc, char** argv)
{
	//获取时间
	srand((unsigned int)time(NULL));
	//创建或者获取一个共享内存
	int shimd = shmget((key_t)1024,sizeof(SHM),0666|IPC_CREAT);
	if(shimd == -1)
	{
		perror("shmget");
		return -1;
	}
	//将共享内存映射到当前的进程空间
	SHM* pshm = (SHM*)shmat(shimd,NULL,0);
	if(pshm == (SHM*)-1)
	{
		perror("shmat");
		return -1;
	}
	//如果命令行参数等于2,负责对共享内存进行初始化
	if(argc == 2)
	{
		pshm->flag = 1;
		pshm->ticket = 100;
	}
	//开始卖票
	sellTicket(pshm);
	
	/*strcpy(pshm->msg,"hello");
	//解除功能共享内存映射,解除是当前进程不能再使用该共享内存 ,不是删除
	shmdt(pshm);*/
	
	
	//对共享内存进行删除
	if(argc == 2)
	{
		shmctl(shimd,IPC_RMID,NULL);
	}
	
	return 0;
}

下面是改进版,首先是.h文件

#ifndef __SEMAPH_H__
#define __SEMAPH_H__

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.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

正文

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
#include <time.h>
#include "semaph.h"

typedef struct _shm
{
	int flag;
	int ticket;
}SHM;

int sellTicket(SHM* pshm,int sem_id)
{
	while(1)
	{
		int time =rand()%10 + 1;
		usleep(time*100000);
		//信号量的P操作
		sem_p(sem_id);
		if(pshm->ticket == 0)
		{
			sem_v (sem_id);
			break;
		}
		printf("卖掉一张票,座位号:%d\n",pshm->ticket);
		pshm->ticket--;
		//V操作	
		sem_v(sem_id);
	}
}
int main(int argc, char** argv)
{
	//获取时间
	srand((unsigned int)time(NULL));
	//创建或者获取一个共享内存
	int shimd = shmget((key_t)1024,sizeof(SHM),0666|IPC_CREAT);
	if(shimd == -1)
	{
		perror("shmget");
		return -1;
	}
	
	//创建一个信号量
	int sem_id =semget((key_t)2048,1,0666|IPC_CREAT);
	if(sem_id == -1)
	{
		perror("semget");
		return -1;
	}
	
	//将共享内存映射到当前的进程空间
	SHM* pshm = (SHM*)shmat(shimd,NULL,0);
	if(pshm == (SHM*)-1)
	{
		perror("shmat");
		return -1;
	}
	//如果命令行参数等于2,负责对共享内存和信号量进行初始化
	if(argc == 2)
	{
		sem_init(sem_id);
		pshm->ticket = 100;
	}
	//开始卖票
	sellTicket(pshm,sem_id);
	
	
	//对共享内存和信号量进行删除
	if(argc == 2)
	{
		shmctl(shimd,IPC_RMID,NULL);
		sem_init(sem_id);
	}
	
	return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值