ImageVerifierCode 换一换
格式:DOCX , 页数:32 ,大小:550.76KB ,
资源ID:9826266      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/9826266.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Linux操作系统利用信号量实现银行叫号排队系统.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Linux操作系统利用信号量实现银行叫号排队系统.docx

1、Linux操作系统利用信号量实现银行叫号排队系统 Linux操作系统课程设计题目:进程通信与进程同步机制实践 (银行叫号排队模拟系统)所在学院: 所在班级: 学生姓名: 学生学号: 指导教师: 一、题目某银行提供5个服务窗口(3个对私服务窗口,1个对公服务窗口,1个理财服务窗口)和10个供顾客等待的座位。顾客到达银行时,若有空座位,则到取号机上领取一个号,等待叫号;若没有空座位,则在门外等待或离开.取号机每次仅允许一位顾客使用,有对公、对私和理财三类号,每位顾客只能选取其中一个.当营业员空闲时,通过叫号选取一位顾客,并为其服务。请用P、V操作写出进程的同步算法。二、目的 1、 掌握基本的同步与

2、互斥算法 。 2、学习使用 Linux 中基本的同步对象,掌握相关 API 的使用方法。 3、了解 Linux 中多任务的并发执行机制,实现进程的同步与互斥 。三、实验环境Linux CentOS、Ubuntu、Fedora等Linux系统编译器GCC编程语言 C语言四、要求1、当有顾客取号的时候,不允许其他顾客取号。2、当服务窗口满的情况下,其他人必须等待.3、当没有顾客的情况下,服务窗口必须等待。4、打印:A、 初始状态B、 中间变化的状态信息C、以及最终状态信息。五、原理及算法本程序中设计6个信号量,其中signal_A、signal_B和signal_C分别是对私、对公、理财窗口的同步

3、信号量。若信号量值的等于0,说明当前没有空闲空口,顾客需要等待。另设置一个signal_seat同步信号量,记录当前的座位情况,若该信号量等于0,说明当前没有空座位,顾客需要等待。另有一个signal_customer同步信号量用于记录当前已经取过票的总人数,用于生成票号信息。还有一个mutex互斥信号量,用于实现各进程在对信号量进行操作时的互斥。顾客进入银行之后,先看通过一个依据系统时间的随机数来确定自己是需要对私、对公还是理财服务(在本程序中分别对应于A类顾客,B类顾客和C类顾客),这三个类型的顾客的比例为3:1:1.然后顾客根据自己需要的服务类型,查看提供相应类型服务的窗口是否空闲,若窗

4、口有空闲,则系统直接按照signal_customer记录的信息,生成票面信息;若窗口没有空闲,则再去查看signal_seat信号量看看是否有空座位,若有空座位,则根据signal_customer记录的信息,生成票面信息;若没有空座位,则通过一个以系统时间为种子的随机数生成器生成一个随机数,帮助顾客确定是要继续等待还是离开,这两种情况的比例为1:1.若顾客选择离开,则相应的进程退出.当顾客取到票后,便开始查看对应类型的窗口是否有空闲,如果有空闲,则上前办理业务。顾客办理业务需要的时长通过以系统时间为种子的随机数生成器来确定,时长均在10秒到60秒之间。在程序执行的过程中,顾客的状态每有变换

5、,都会有相应的输出提示信息,并在输出的行尾输出发生该动作时当前的系统时间,以便于我们分析各个顾客进程的执行情况。本实验在Linux环境下完成,该程序是通过进程实现的.包含一个service可执行文件,一个customer可执行文件和一个deletesem可执行文件。其中service可执行文件用于在内存中申请一个共享内存空间,并将这个内存空间与自身进程绑定;customer可执行文件每执行一次,就增加一个进程,即代表有一位顾客来到.通过多次执行customer可执行文件来模拟多位顾客;deletesem可执行文件用于在service进程和customer进城都执行完毕后,删除内存空间中的信号集

6、。实验中利用GCC编译器,通过编写Makefile文件来快速编译源代码生成以上三个可执行文件。六、程序中各主要函数说明1、int createshm( char pathname, int proj_id, size_t size)创建共享内存的函数,操作成功则返回共享内存标识符,失败返回-1.2、int createsem (const char pathname, int proj_id, int members, int init_val)在共享内训中创建信号量的函数,操作成功则返回信号集标识符,失败返回-1.3、int opensem(const char * pathname, in

7、t proj_id)打开信号集函数,操作成功则返回信号集标识符,失败返回-1。4、int sem_p(int semid, int index)P操作函数,操作成功则返回0,失败返回1.5、int sem_v(int semid, int index)V操作函数,操作成功则返回0,失败返回-1。6、int wait_sem(int semid, int index)等待信号量为1函数,操作成功返回1.7、int delete_sem (int semid)删除信号集函数,操作成功返回0。8、int get_sem_val (int semid ,int index)获取指定信号集中指定下标的信

8、号量的值,操作成功返回该信号量的值。9、int my_random()自定义随机数生成器,以系统时间为种子,每次执行前延时1秒,以便于生成不同的随机数。10、void print_time()打印当前系统时间。11、int get_ticket(int semid, char identifyLabel, int ticket, int * flag)顾客取票函数,取票成功,返回1,失败返回-1,,由于没有空座,顾客选择离开则返回0.12、void service(int semid, char identifyLabel, int ticket, int flag)顾客办理业务函数。七、源程

9、序清单sharemem。h文件includestdio。hincludeinclude#includesys/types.hincludesys/ipc。h#includeincludesys/shm.hincludeincludetime。h#define SHM_SIZE 1024define INDEX_MUTEX 0define INDEX_SIGNAL_SEAT 1#define INDEX_SIGNAL_CUSTOMER 2define INDEX_SIGNAL_A 3#define INDEX_SIGNAL_B 4#define INDEX_SIGNAL_C 5/定义信号量/*同

10、步信号量一共有4个/int signal_A=3, signal_B=1, signal_C=1, signal_seat=3, signal_customer=0;/互斥信号量mutex控制进程对每个同步信号量的操作*/int mutex=1;int signal_count=6; /信号量计数器,记录一共有多少信号量union semun int val; struct semid_ds buf; unsigned short array;;/*创建共享内存函数/int createshm( char pathname, int proj_id, size_t size) key_t sh

11、mkey; int sid; /获取键值*/ if ((shmkey=ftok(pathname, proj_id)=1) perror (ftok error!n); exit(1); return -1; if ((sid=shmget(shmkey, size, IPC_CREAT | 0666))=-1) perror (shmget call failed。n”); exit(1); return -1; return (sid);/定义创建信号量的函数*/int createsem (const char * pathname, int proj_id, int members,

12、int init_val) key_t msgkey; int index,sid; union semun semopts; if (msgkey=ftok(pathname, proj_id)=1) perror (”ftok error!n); exit(1); return -1; if((sid=semget(msgkey, members, IPC_CREAT | 0666)=1) perror (”semget call failed.n”); exit(1); return 1; /*对信号量进行初始化操作/ for(index=0;indexmembers;index+) s

13、emopts.val=init_valindex; /根据init_val数组中的值对各个信号量进行初始化 semctl (sid,index,SETVAL,semopts); return (sid);/打开信号量函数/int opensem(const char pathname, int proj_id) key_t msgkey; int sid; if ((msgkey=ftok(pathname,proj_id))=-1) perror (”ftok error!n); exit(1); return 1; if((sid=semget(msgkey, 0 ,IPC_CREAT |

14、 0666)=1) perror (”semget call failed。n”); exit(1); return -1; return (sid);/*P操作函数/int sem_p(int semid, int index) struct sembuf buf=0,-1,IPC_NOWAIT; if(index 0) /检查,如果有空窗口,则直接取票,不用判断座位 *flag=0; /将标志为设为0,标示没有顾客在等待,不用排队 goto goto_A; /跳转到直接取票 if( wait_sem(semid, INDEX_SIGNAL_SEAT) ) /如果没有空座,则等待空座 sem

15、_p(semid, INDEX_SIGNAL_SEAT); goto_A: if( wait_sem(semid, INDEX_MUTEX) ) /等待操作信号量释放 sem_p(semid, INDEX_MUTEX); /锁定操作信号量 ticket=get_sem_val(semid, INDEX_SIGNAL_CUSTOMER) + 1; /分配票号(票号是根据当天的总顾客数排的) wait_num = (signal_seat get_sem_val(semid,INDEX_SIGNAL_SEAT) ) -1; /获取当前等待的人数 printf(”号码:A%03d,”,ticket)

16、; if(wait_num=0 | *flag=0) printf(”当前没有顾客正在等待。t); /wait_num大于等于0或者flag大于0,表示当前无人等待 print_time(); else printf(”有d位顾客正在等待。t”,wait_num); print_time(); printf(”顾客A%03d正在等待办理业务。t”,*ticket); print_time(); if( sem_v(semid, INDEX_SIGNAL_CUSTOMER) !=0) /记录目前办理过业务和等待办理业务的顾客总数 printf(对不起,V操作失败!”); exit(1); ret

17、urn 1; sem_v(semid, INDEX_MUTEX); /释放控制进程访问资源的信号量 break; case B: if(get_sem_val(semid, INDEX_SIGNAL_SEAT) = 0) if( (wait_num=my_random()10)5) return 0; /返回0表示顾客选择离开 printf(”目前没有空座位,但该顾客选择了等待。nn”); if(get_sem_val(semid, INDEX_SIGNAL_B) 0) /检查,如果有空窗口,则直接取票,不用判断座位 flag=0; /将标志为设为0,标示没有顾客在等待,不用排队 goto g

18、oto_B; /跳转到直接取票 if( wait_sem(semid, INDEX_SIGNAL_SEAT) ) /如果没有空座,则等待空座 sem_p(semid, INDEX_SIGNAL_SEAT); goto_B: if( wait_sem(semid, INDEX_MUTEX) ) /等待操作信号量释放 sem_p(semid, INDEX_MUTEX); /锁定操作信号量 *ticket=get_sem_val(semid, INDEX_SIGNAL_CUSTOMER) + 1; /分配票号(票号是根据当天的总顾客数排的) wait_num = (signal_seat get_s

19、em_val(semid,INDEX_SIGNAL_SEAT) ) -1; /获取当前等待的人数 printf(号码:B03d,,*ticket); if(wait_num=0 | *flag=0) printf(”当前没有顾客正在等待。t); /wait_num大于等于0或者flag大于0,表示当前无人等待 print_time(); else printf(有%d位顾客正在等待。t”,wait_num); print_time(); printf(顾客B%03d正在等待办理业务.t,*ticket); print_time(); if( sem_v(semid, INDEX_SIGNAL_

20、CUSTOMER) !=0) /记录目前办理过业务和等待办理业务的顾客总数 printf(”对不起,V操作失败!”); exit(1); return 1; sem_v(semid, INDEX_MUTEX); /释放控制进程访问资源的信号量 break; case C: if(get_sem_val(semid, INDEX_SIGNAL_SEAT) = 0) if( (wait_num=my_random()%10)5) return 0; /返回0表示顾客选择离开 printf(”目前没有空座位,但该顾客选择了等待.nn”); if(get_sem_val(semid, INDEX_SI

21、GNAL_C) 0) /检查,如果有空窗口,则直接取票,不用判断座位 flag=0; /将标志为设为0,标示没有顾客在等待,不用排队 goto goto_C; /跳转到直接取票 if( wait_sem(semid, INDEX_SIGNAL_SEAT) ) /如果没有空座,则等待空座 sem_p(semid, INDEX_SIGNAL_SEAT); goto_C: if( wait_sem(semid, INDEX_MUTEX) ) /等待操作信号量释放 sem_p(semid, INDEX_MUTEX); /锁定操作信号量 *ticket=get_sem_val(semid, INDEX_

22、SIGNAL_CUSTOMER) + 1; /分配票号(票号是根据当天的总顾客数排的) wait_num = (signal_seat get_sem_val(semid,INDEX_SIGNAL_SEAT) ) 1; /获取当前等待的人数 printf(”号码:C%03d,,*ticket); if(wait_num=0 | flag=0) printf(当前没有顾客正在等待。t); /wait_num大于等于0或者flag大于0,表示当前无人等待 print_time(); else printf(”有d位顾客正在等待。t”,wait_num); print_time(); printf(

23、顾客C03d正在等待办理业务。t”,ticket); print_time(); if( sem_v(semid, INDEX_SIGNAL_CUSTOMER) !=0) /记录目前办理过业务和等待办理业务的顾客总数 printf(”对不起,V操作失败!); exit(1); return 1; sem_v(semid, INDEX_MUTEX); /释放控制进程访问资源的信号量 break; return 1;/*顾客接受服务函数*/void service(int semid, char identifyLabel, int * ticket, int flag) int need_time=0; /用于记录

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1