山东大学操作系统实验五理发师问题报告
山东大学操作系统OS作业1-5分析复习进程
操作系统作业 1-5章软件5班张** 201200301311第一章1.1a.个人的程序或者数据可能遭到窃取多人同时使用时可能造成cpu拥堵b.不能。
所有保护机制都有可能被外人破译,所以共用系统一定没有单独使用系统安全。
1.10(1)现代操作系统是由中断驱动的,中断可以改变对系统的控制权。
中断可以使一些需要立即响应的进程及时得到处理,并且不影响原进程的运行。
(2)陷阱即为异常,是一种软件中断,源于出错。
而中断不一定是出错,可能是来自I/O的一个命令,可能为硬件中断。
(3)用户可以有意生成陷阱。
目的是为了避免一个进程的错误影响到很多进程,如死循环发生时就可以通过陷阱避免影响。
1.12操作系统需要在任何时刻都可被控制,故可以构建的安全的操作系统为:所有用户程序通过软件实现。
所有的程序都有高级编程语言编写,以便所有目标代码都被编译出来1.17a.批处理:具有相似需求的作业被成批的集合起来,并把它们作为一个整体通过一个操作员或自动作业程序装置运行通过计算机。
通过缓冲区,线下操作,后台和多道程序,运用尝试保持 CPU 和 I/O 一直繁忙,从而使得性能被提高。
批处理系统对于运行那些需要较少互动的大型作业十分适用。
它们可以被更迟地提交或获得。
b.交互式:这种系统由许多短期交易构成,并且下一个交易的结果是无法预知的。
从用户提交到等待结果的响应时间应该是比较短的,通常为 1 秒左右。
c.分时:分时系统中,CPU通过在作业之间的切换来执行多个作业,但是由于切换的频率很高,用户可以在程序运行期间与之进行交互。
d.实时:系统能够在限定的时间内提供用户要求的服务。
e.网络:提供给操作系统一个特征,使得其进入网络,比如文件共享。
f.并行:有多个紧密通信的CPU,它们共享计算机总线,有时还有时钟,内存,外设等。
g.分布:这种系统在几个物理处理器中分布式计算,处理器不共享内存或时钟。
每个处理器都有它各自的本地存储器。
它们通过各种通信线路在进行通信,比如:一条高速的总线或一个本地的网络。
操作系统实验报告 附思考题
课程设计(综合实验)报告( 2015 -- 2016 年度第 1 学期)名称:操作系统综合实验题目:oslab综合实验院系:计算机系班级:学号:学生姓名:指导教师:设计周数:分散进行成绩:日期:2015 年10 月29 日实验1 实验环境的使用一、综合实验的目的与要求熟悉操作系统集成实验环境OS Lab 的基本使用方法。
练习编译、调试EOS 操作系统内核以及EOS 应用程序。
二、实验正文1.启动 OS Lab2.1 执行项目Windows 控制台窗口内容显示2.2 调试项目2.2.1 使用断点中断执行2.2.2 单步调试2.2.2 .3单步调试结果显示:练习使用“逐语句”功能和“跳出”功能2.2.3 查看变量的值快速监视添加监视2.2.4 调用堆栈调用堆栈显示内容进入Func 函数双击 main 函数所在的行表示此函数是当前调用堆栈中的活动函数。
3 新建EOS 内核项目4 EOS 应用程序项目的生成和调试4.1 新建EOS 应用程序项目4.2 调试项目添加断点后单步调试结果显示4.3 查看软盘镜像文件中的内容4.4修改EOS 应用程序项目名称5 退出OS Lab6 保存EOS 内核项目三、综合实验总结或结论思考与练习:1.在哪些情况下应该使用“逐过程”调试,在哪些情况下应该使用“逐语句”调试。
答:逐语句为每执行一行语句,如果碰到函数调用它就会进入到函数里面。
而逐过程碰到函数时不进入函数,把函数调用当成一条语句去执行。
2. 生成EOS SDK 文件夹的目的和作用。
明白文件夹的组织结构和各个文件的来源和作用。
查看EOS 应用程序包含了SDK 文件夹中的哪些头文件,是如何包含的?(1)EOS SDK为应用程序调用系统API提供服务,可作为用户编程中使用的工具包集合。
(2)其主要包括INC头文件LIB文件夹、导入库文件和BIN文件夹、动态链接库、可执行程序、二进制文件。
(3)包含的头文件有:eos.h负责导出API函数,eosdef.h声明负责导出函数类型的定义,error.h负责导出错误码。
操作系统课程设计实验报告(附思考题答案)
操作系统课程设计实验报告(附思考题答案)课程设计(综合实验)报告( 2015 -- 2016 年度第 1 学期)名称:操作系统综合实验题目:oslab综合实验院系:计算机系班级:学号:学生姓名:指导教师:设计周数:分散进行成绩:日期:2015 年10 月29 日一、综合实验的目的与要求1. 理解和掌握操作系统的基本概念、基本组成与工作原理;2. 理解和掌握操作系统中主要功能模块的工作原理及其实现算法;3. 掌握软件模块设计技能;熟悉并能较好地利用软件开发环境独立编程、调试和分析程序运行情况,逐渐形成创新思维和从事系统软件的研究和开发能力。
二、实验正文实验1:实验环境的使用1.1实验目的:1.熟悉操作系统集成实验环境OS Lab 的基本使用方法。
2.练习编译、调试EOS 操作系统内核以及EOS 应用程序。
1.2实验内容:1.启动OS Lab2.学习OS Lab 的基本用法● 新建 Windows 控制台应用程序项目(1)在“文件”菜单中选择“新建”,然后单击“项目”。
(2)在“新建项目”对话框中,选择项目模板“控制台应用程序(c)”。
(3)在“名称”中输入新项目使用的文件夹名称“oslab ”。
(4)在“位置”中输入新项目保存在磁盘上的位置“C:\test ”。
(5)点击“确定”按钮。
● 生成、执行项目●3.EOS 内核项目的生成和调试● 新建 EOS 内核项目并按F7生成项目● 调试项目● 查看软盘镜像文件中的内容、EOS SDK (Software Development Kit )文件夹4.EOS 应用程序项目的生成和调试● 新建 EOS 应用程序项目● 修改 EOS 应用程序项目名称使用断点中断执行查看变量的值5.退出OS Lab6.保存EOS内核项目1.3思考与练习●在实验1中,生成EOS SDK文件夹的目的和作用是什么?答:SDK文件夹中提供了开发EOS应用程序需要的所有文件。
debug文件夹是在使用debug配置生成项目时生成的,其中存放了调试版本的EOS二进制文件。
山东大学计算机学院操作系统实验报告
操作系统课程设计报告学院:计算机科学与技术学院专业:计算机科学与技术班级:20**级*班姓名:***学号:20**********目录一实验平台 (2)二Project1建立线程系统 (2)Task1.1实现KThread.join() (2)1.要求 (2)2.分析 (2)3.方案 (3)4.实现代码 (3)Task1.2利用中断提供原子性,直接实现条件变量 (4)1.要求 (4)2.分析 (5)3.方案 (5)4.实现代码 (5)Task1.3实现waitUntil (7)1.要求 (7)2.分析 (7)3.方案 (7)4.实现代码 (8)Task1.4用条件变量,不使用信号量,实现同步发送接收消息,speak,listen (10)1.要求 (10)2.分析 (10)3.方案 (11)4.实现代码 (11)Task1.5完成PriorityScheduler实现优先级调度 (13)1.要求 (13)2.分析 (13)3.方案 (14)4.实现代码 (14)Task1.6 (17)1.要求 (17)2.分析 (18)3.方案 (19)4.实现代码 (19)三Project2多道程序设计 (27)Task2.1 (27)1.要求 (27)2.分析 (28)3.方案 (28)4.实现代码 (31)Task2.2 (36)1.要求 (36)2.分析 (36)3.方案 (36)4.实现代码 (38)Task2.3 (43)1.要求 (43)2.分析 (43)3.方案 (44)4.实现代码 (45)Task2.4 (47)1.要求 (47)2.分析 (48)3.方案 (48)4.实现代码 (48)一实验平台开发语言:Java开发工具:Eclipse Luna操作系统:Ubuntu14.04二P roject1建立线程系统Task1.1实现KThread.join()1.要求实现Implement KThread.join()函数。
计算机操作系统理发师问题-JAVA
课程实验报告题目计算机操作系统理发师问题姓名潘 *学号 2013 ***年级专业2013级*指导教师彭 * 华201*年1*月 30 日一题目假设有个理发店,只有一个理发师和N张可供顾客等待理发的椅子,如果没有顾客,则理发师睡觉,如果有一个顾客进入理发店发现理发师在睡觉,则把他叫醒,试用信号量设计一个协调理发师和顾客的程序。
二 PV操作伪代码C语言的伪代码实现:int waiting=0 ;//等候理发的顾客数int chairs=n;//为顾客准备的椅子数semaphore customers=0, barbers=0,mutex=1;barber() {while(TRUE); //理完一人,还有顾客吗?P(cutomers); //若无顾客,理发师睡眠P(mutex); //进程互斥waiting -= 1;//等候顾客数少一个V(barbers); //理发师去为一个顾客理发V(mutex); //开放临界区cut-hair(); //正在理发}customer() {P(mutex); //进程互斥if(waiting) {waiting += 1; // 等候顾客数加1V(customers); //必要的话唤醒理发师V(mutex); //开放临界区P(barbers); //无理发师, 顾客坐着养神get-haircut( ); //一个顾客坐下等理/}else V(mutex); //人满了,离开}三程序流程图顾客模块:理发师模块:四源程序的实现因为本人对C++的多线程库函数不了解,于是使用JAVA实现理发师问题,假设有5张可供顾客理发的椅子:package com.swxy;import java.util.concurrent.Semaphore;//导入Semaphore,用于控制进程同步互斥的量。
public class BarberShop {static int cnt = 0;// 顾客static int MAX = 5;// 假设5张可供顾客理发的椅子static int busy = 0;static Semaphore mutex= new Semaphore(1);// 临界区互斥访问信号量(二进制信号量),相当于互斥锁。
操作系统实验报告三大问题之生产者与消费者问题
计算机操作系统实验报告题目三大经典问题之生产者与消费者问题一、课程设计的性质与任务1、加深对并发协作进程同步与互斥概念的理解。
通过编写程序实现进程同步和互斥,使学生掌握有关进程(线程)同步与互斥的原理,以及解决进程(线程)同步和互斥的算法,从而进一步巩固进程(线程)同步和互斥等有关的内容。
2、掌握进程和线程的概念,进程(线程)的控制原语或系统调用的使用。
3、了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。
学习使用Windows2000/XP中基本的同步对象,掌握相应的API函数。
4、培养学生能够独立进行知识综合,独立开发较大程序的能力。
5、培养提高学生软件开发能力和软件的调试技术。
6、培养学生开发大型程序的方法和相互合作的精神。
7、培养学生的创新意识。
8、培养学生的算法设计和算法分析能力。
9、培养学生对问题进行文字论述和文字表达的能力。
二、课程设计的内容及其要求在Windows?XP、Windows?2000等操作系统下,使用的VC、VB、Java或C等编程语言,采用进程(线程)同步和互斥的技术编写程序实现生产者消费者问题或哲学家进餐问题或读者-写者问题或自己设计一个简单进程(线程)同步和互斥的实际问题。
要求:(1)经调试后程序能够正常运行。
(2)采用多进程或多线程方式运行,体现了进程(线程)同步互斥的关系。
(3)程序界面美观。
三、实验原理本实验要求利用PV操作实现解决生产者——消费者问题中的同步问题。
此问题描述的是一群生产者进程在生产产品并将这些产品提供给消费者进程去消费,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将它所生产的产品放入一个缓冲区,消费者进程可从缓冲区中取走产品去消费,但它们之间必须保持同步,即不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装满且尚未取出的缓冲区中投放产品,并且生产者消费者互斥使用缓冲区。
四、实验原理图五、算法实现(1)有一个生产者线程ProduceThread,有1个消费者进程CustomerThread;缓冲区为shareList。
理发师问题操作系统课程设计
理发师问题操作系统课程设计河南城建学院《操作系统》课程设计报告课程名称: 《操作系统》课程设计设计题目: 理发师问题指导教师: 李蓓耿永军班级:学号:学生姓名:同组人员:成绩:评语:计算机科学与工程学院2014年6月19日前言现在计算机更新如此迅速的时代要学好计算机软件技术,特别是操作系统的学习,不仅要努力学好课本上的基础知识,还要经常在图书馆看些有关这方面的书籍,而更重要的是要有足够的实践经验,也要注重和同学的交流,经常尝试性的做些小的操作系统,对自己技术的提升会有很大的帮助。
同时,学习计算机操作系统技术,除了需要刻苦努力外,还需要掌握软件和操作系统的原理与设计技巧。
如何学习和掌握操作系统技术的原理与实际技巧呢?除了听课和读书之外,最好的方法恐怕就是在实践中练习。
例如,自己设计一个小型操作系统,多使用操作系统,多阅读和分析操作源代码等。
但由于我们的条件和学时有限,在理论学习过程中没有给同学们提供更多的实验机会。
本操作系统课程设计,是给同学提供一个集中实验的机会。
希望同学们通过该设计加深对所学习课程的理解。
本设计的内容是基于《操作系统原理》、《C语言程序设计》和《数据结构》等内容。
本设计是基于课程中学到的UNIX系统调用,使用操作系统环境是Red Hat Linux 9,言语开发环境是Linux的GNU C或C++。
完成本次课程设计,首先必须配置操作系统编写的所需的环境,包括虚拟机的建立和相应环境建立。
用VI编辑器编写相应得程序,以实现理发师进程的同步与互斥。
目录第一章.系统环境 ..................................................................... .. (1)1.1硬件环境 ..................................................................... . (1)1.2软件环境 ..................................................................... . (1)第二章.设计目的及要求 ..................................................................... .. (2)2.1设计目的 ..................................................................... . (2)2.2 要求 ..................................................................... .. (2)2.3 内容 ..................................................................... .. (2)第三章.总体设计 ..................................................................... .. (3)3.1程序设计组成框图 ..................................................................... (3)3.2 主函数流程图 ..................................................................... . (4)3.3理发师进程流程图 ..................................................................... (5)3.4 顾客进程流程图 ..................................................................... (5)3.5函数调用 ..................................................................... . (6)第四章.详细设计 ..................................................................... .. (7)4.1概要设计 ..................................................................... . (7)4.1.1 数据结构 ..................................................................... .. (7)4.1.2 多线程编译原理 ..................................................................... .. (7)4.1.3 创建线程 ..................................................................... .. (7)4.1.4 信号量 ..................................................................... (8)4.2 头文件声明 ..................................................................... .. (8)4.3函数定义 ..................................................................... . (9)4.4 变量定义 ..................................................................... (9)4.5函数实现 ..................................................................... . (9)第五章.调试与测试 ..................................................................... .. (11)5.1调试方法 ..................................................................... .. (11)5.2结果分析 ..................................................................... ..................................................... 13 第六章.设计中遇到的问题及解决方法 ..................................................................... (14)6.1出现的问题 ..................................................................... . (14)6.2解决方法 ..................................................................... ..................................................... 14 第七章.源程序清单和执行结果 ..................................................................... (16)7.1源程序清单 ..................................................................... . (16)7.2程序执行结果 ..................................................................... ............................................. 19 第八章.心得体会 ..................................................................... (20)第九章.参考文献 ..................................................................... (21)1 《操作系统》课程设计第一章.系统环境1.1硬件环境内存1GB,处理器1,硬盘(SCSI)50GB,网络适配器NAT。
操作系统--理发师问题
设计思想的说明:打瞌睡的理发师问题是一种同步问题的抽象描述。
计算机系统中的每个进程都可以消费或生产某类资源,当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。
而当某个进程释放资源时,则它就相当一个生产者。
因此此题可看作是n个生产者和1个消费者问题。
顾客作为生产者,每到来一个就使计数器count增加1,以便让理发师理发(相当于消费)至最后一个顾客(相当于产品)。
并且,第1个到来的顾客应负责唤醒理发师;如果不是第1个到达的顾客,则在有空椅子的情况下坐下等待,否则离开理发店(该消息可由计数器count获得),所以可以通过一个有界缓冲区把理发师和顾客联系起来通过对信号进行P、V操作来实现有关问题和相关描述。
源程序文件:#include<windows.h>#include<stdio.h>#include<iostream>#include<process.h>#include<conio.h>#include<ctime>using namespace std;#define CHAIRS 3 //椅子的个数#define BARBERS 1 //理发师的个数#define CUSTOMESTOCOME 7 //将要来的顾客的数目typedef HANDLE semaphore;static int count=0; //记录理发店顾客的总数,初始化为0int leaved=0; //记录理发店顾客的总数,初始化为0int waiting=0;time_t endtime; //关闭营业的时间//coustomers初始化为0,最大顾客数为3semaphore customers=CreateSemaphore(NULL,0,CHAIRS,TEXT("customers")); //barbers的数量初始化为1,假设一共有1个barbersemaphorebarbers=CreateSemaphore(NULL,BARBERS,BARBERS,TEXT("barbers"));//建立互斥变量,用于保护共享资源HANDLE mutex=CreateMutex(NULL,FALSE,TEXT("mutex"));DWORD WINAPI barber(LPVOID lparameter);DWORD WINAPI customer(LPVOID lparameter);//理发师理发void cutHair();//顾客坐到椅子上等待void getChair();//等待顾客到来void wait();//顾客离开void customerLeave();//顾客进入void customerEnter();void up(HANDLE hHandle){//对指定信号量增加指定的值ReleaseSemaphore(hHandle,1,NULL);//恢复线程ResumeThread(hHandle);}void upMutex(HANDLE hMutex){//释放线程拥有的互斥体ReleaseMutex(hMutex);}void down(HANDLE hHandle){ //DOWN operation//线程挂起,等待信号WaitForSingleObject(hHandle,INFINITE);}int main(){//结束时间endtime=time(0)+20000;//创建理发师线程HANDLE barberThread=CreateThread(NULL,0,barber,NULL,0,NULL);HANDLE customerThread;//产生10个客户进程,每两个进程之间间隔一个随见时间1000~1050 while(count<CUSTOMESTOCOME){//创建客户进程customerThread=CreateThread(NULL,0,customer,NULL,0,NULL);srand(unsigned(time(0)));int time=rand()%1000+50;Sleep(time);}//释放资源CloseHandle(barberThread);CloseHandle(customerThread);CloseHandle(barbers);CloseHandle(customers);CloseHandle(mutex);cout<<"离开的顾客总数为:"<<leaved<<endl;return 0;}DWORD WINAPI barber(LPVOID lparameter) {while(time(0)<endtime){//没有客户,则进入睡眠状态down(customers);//临界区操作down(mutex);waiting=waiting-1;upMutex(mutex);//开始理发cutHair();//理发结束,理发师信号量加1up(barbers);}return 0;}DWORD WINAPI customer(LPVOID lparameter){ //客户到来customerEnter();//临界区操作down(mutex);cout<<"等̨¨待äy的Ì?顾?客¨ª数ºy: "<<waiting<<endl;cout<<"空?椅°?子Á¨®数ºy: "<<CHAIRS-waiting<<endl;if(waiting<CHAIRS){ //如果有空椅子,客户等待,否则离开if(waiting!=0){//等待顾客到来wait();}waiting=waiting+1;//客户信号量加1up(customers);upMutex(mutex);//离开临界区//理发师进程等待唤醒down(barbers);//顾客坐下来等待getChair();}else{//释放互斥锁upMutex(mutex);//顾客离开customerLeave();}return 0;}void cutHair(){static int served=0;served++;cout<<理发师帮第"<<served<<"位被服务的顾客理发"<<endl;Sleep(1000);cout<<"第"<<served<<"位被服务的顾客理完发"<<endl;}void getChair(){Sleep(1050);}void customerEnter(){count++;SYSTEMTIME sys;GetLocalTime( &sys );cout<<endl<<"第"<<count<<"位顾客进来"<<endl;}void wait(){cout<<"有空位,第"<<count<<"位顾客就坐"<<endl;}void customerLeave(){cout<<"没有空椅子,第"<<count<<"位顾客离开 ."<<endl;leaved++;}输出截图:PS:由于我对c++中处理进程、信号的函数不熟,所以有许多参考了网上的代码。
山东大学操作系统试验报告
计算机科学与技术学院操作系统实验报告学院:专业:班级:姓名:学号:日期:Email:目录实验一进程控制实验 (4)1.1实验目的 (4)1.2实验题目 (4)1.3实验步骤 (4)1.4结论分析与体会 (5)1.5附录:本实验全部程序源代码及注释 (5)1.5.1Pctl.c (5)1.5.2pctl.h (9)1.5.3makefile (10)实验三进程调度算法实验 (10)3.1实验目的 (10)3.2实验题目 (11)3.3实验步骤 (11)3.4结论分析与体会 (12)3.5附录:本实验全部程序源代码及注释 (12)3.5.1Psched.c (12)3.5.2Psched.h (14)3.5.3Makefile (16)实验四进程同步实验 (16)4.1实验目的 (16)4.2实验题目 (16)4.3实验步骤 (17)4.4结论分析与体会 (24)4.5附录:本实验全部程序源代码及注释 (24)4.5.1Ipc.c (24)4.5.2Ipc.h (32)4.5.3Consumer (35)4.5.4Producer (41)4.5.5makefile (50)实验七内存页面置换算法实验 (51)7.1实验目的 (51)7.2实验题目 (51)7.3实验步骤 (52)7.4附录:本实验全部程序源代码及注释 (55)7.4.1Vmrp.h (55) (57)7.5.3makefile (73)实验八磁盘移臂调度算法实验 (74)7.2实验目的 (74)8.2实验题目 (74)8.3实验步骤 (75)8.4附录:本实验全部程序源代码及注释 (76)8.4.1Dask.h (76) (78)8.4.3Makefile (94)实验一进程控制实验1.1 实验目的加深对于进程并发执行概念的理解。
实践并发进程的创建和控制方法。
观察和体验进程的动态特性。
进一步理解进程生命期期间创建、变换、撤销状态变换的过程。
计算机操作系统理发师问题-JAVA模板
课程实验报告题目计算机操作系统理发师问题姓名潘 *学号 2013 ***年级专业2013级*指导教师彭 * 华201*年1*月 30 日一题目假设有个理发店,只有一个理发师和N张可供顾客等待理发的椅子,如果没有顾客,则理发师睡觉,如果有一个顾客进入理发店发现理发师在睡觉,则把他叫醒,试用信号量设计一个协调理发师和顾客的程序。
二 PV操作伪代码C语言的伪代码实现:int waiting=0 ;//等候理发的顾客数int chairs=n;//为顾客准备的椅子数semaphore customers=0, barbers=0,mutex=1;barber() {while(TRUE); //理完一人,还有顾客吗?P(cutomers); //若无顾客,理发师睡眠P(mutex); //进程互斥waiting -= 1;//等候顾客数少一个V(barbers); //理发师去为一个顾客理发V(mutex); //开放临界区cut-hair(); //正在理发}customer() {P(mutex); //进程互斥if(waiting) {waiting += 1; // 等候顾客数加1V(customers); //必要的话唤醒理发师V(mutex); //开放临界区P(barbers); //无理发师, 顾客坐着养神get-haircut( ); //一个顾客坐下等理/}else V(mutex); //人满了,离开}三程序流程图顾客模块:理发师模块:四源程序的实现因为本人对C++的多线程库函数不了解,于是使用JAVA实现理发师问题,假设有5张可供顾客理发的椅子:package com.swxy;import java.util.concurrent.Semaphore;//导入Semaphore,用于控制进程同步互斥的量。
public class BarberShop {static int cnt = 0;// 顾客static int MAX = 5;// 假设5张可供顾客理发的椅子static int busy = 0;static Semaphore mutex= new Semaphore(1);// 临界区互斥访问信号量(二进制信号量),相当于互斥锁。
山东大学操作系统实验报告
操作系统实验报告计算机科学与技术学院目录一、进程控制实验实验目的加深对于进程并发执行概念的理解。
实践并发进程的创建和控制方法。
观察和体验进程的动态特性。
进一步理解进程生命期期间创建、变换、撤销状态变换的过程。
掌握进程控制的方法,了解父子进程间的控制和协作关系。
练习 Linux 系统中进程创建与控制有关的系统调用的编程和调试技术。
示例实验实验内容以下实验示例程序应实现一个类似shell 子命令的功能,它可以从执行程序中启动另一个新的子进程并执行一个新的命令和其并发执行。
实验演示结果独立实验实验内容参考以上示例程序中建立并发进程的方法,编写一个父子协作进程,父进程创建一个子进程并控制它每隔 3 秒显示一次当前目录中的文件名列表。
实验步骤算法设计通过进程间的通讯,先创建一个父进程一个子进程,父进程沉睡3秒,子进程作为当前父进程再次创建一个他的子进程,当前子进程执行显示当前目录文件列表功能,执行execve()方法后死亡。
While(1)在死循环里无限进行当前操作。
即达到父进程创建一个子进程并控制它每隔3秒显示一次当前目录中的文件名列表的要求。
开发调试过程打开一终端命令行窗体,新建一个文件夹,在该文件夹中建立名为的C语言程序;再建立以下名为的 C 语言头文件;建立项目管理文件 Makefile;输入 make 命令编译连接生成可执行的 pctl 程序;执行 pctl 程序;再次执行带有子进程指定执行命令的 pctl 程序。
思考与分析1.反映的进程的特征和功能,在真实的操作系统中是怎样实现和反映出教材中讲解的进程的生命期、进程的实体和进程状态控制的。
对于进程概念和并发概念有哪些新的理解和认识子进程是如何创建和执行新程序的答:进程是一个可并发执行的程序在某数据集上的一次运行,是程序的一次运行过程。
而程序只是进程的一个组成部分,进程是程序的执行过程。
程序是静态的指令集合,而进程是动态的过程实体,是动态的产生、发展和消失。
操作体统实验报告
中山大学南方学院实验报告课目:操作系统姓名:陈瑞全班级:08级电子一班指导老师:梁路哲学家就餐问题一、实验题目:解决五个哲学家就餐问题二、设计内容:三、开发环境:四、分析设计:1.给五个哲学家编号为1,2,3,4,5;产生一个1~5之间的随机数,规定一次产生两个哲学家;2.设置一个全局变量,将上一次产生的信号量纪录在内,并判断此次与上次的编号是否相差2或3;若是,即可同时吃,并释放上一个哲学家的筷子,若不是,只释放上一个哲学家的筷子。
3.作N次循环(N自己输入)五个哲学家围坐在一圆桌旁,桌中央有一盘菜,每人面前有一只空盘子,每两人之间放一只筷子每个哲学家的行为是思考,感到饥饿,然后吃菜.为了吃菜每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子#define N 5void philosopher (int i){while (true){思考;取fork[i]; 取fork[(i+1) % 5];进食;放fork[i]; 放fork[(i+1) % 5];}}为防止死锁发生可采取的措施:最多允许4个哲学家同时坐在桌子周围仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子()给所有哲学家编号,奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则反之为了避免死锁,把哲学家分为三种状态,思考,饥饿,进食,并且一次拿到两只筷子,否则不拿.哲学家就餐问题解法(1)#define N 5void philosopher (int i){while (true){思考;取fork[i]; 取fork[(i+1) % 5];进食;放fork[i]; 放fork[(i+1) % 5];}}哲学家就餐问题解法(2)#define N 5#define THINKING 0#define HUNGRY 1#define EATING 2#typedef int semaphore;int state[N];semaphore mutex=1;semaphore s[N];void test(int i){if (state[ i ] == HUNGRY)&& (state [ (i-1) % 5] != EATING)&& (state [ (i+1) % 5] != EATING){state[ i ] = EATING;V(&s[ i ]);}}void philosopher (int i){ while (true){思考;P(&mutex);state[i] = HUNGRY;test(i);V(&mutex);P(&s[i]);拿左筷子;拿右筷子;进食;放左筷子; 放右筷子;P(&mutex)state[ i ] = THINKING;test([i-1] % 5);test([i+1] % 5);V(&mutex);}}state[ i ] = THINKINGs[ i ] = 0为每个哲学家使用POSIX线程(pthread)建立独立的线程(有独立的id),用互斥(叉子其他哲学家使用时,另一个哲学家不能使用)和条件(哲学家饿了才尝试去得到叉子,得到相邻的左右两把叉子才能进餐)来分到叉子。
理发师问题-信号量实现版
理发师问题-信号量实现版问题描述:⼀个理发店由⼀个有⼏张椅⼦的等待室和⼀个放有⼀张理发椅的理发室组成。
1.若没有要理发的顾客,则理发师去睡觉;2.若⼀顾客进⼊理发店,理发师正在为别⼈理发,且等待室有空椅⼦,则该顾客就找张椅⼦按顺序坐下;3.若⼀顾客进⼊理发店,理发师在睡觉,则叫醒理发师为该顾客理发;4.若⼀顾客进⼊理发店且所有椅⼦都被占⽤了,则该顾客就离开。
伪码实现:引⼊3个信号量和⼀个控制变量:1)控制变量waiting⽤来记录等候理发的顾客数,初值均为0;2)信号量customers⽤来记录等候理发的顾客数,并⽤作阻塞理发师进程,初值为0;3)信号量barbers⽤来记录正在等候顾客的理发师数,并⽤作阻塞顾客进程,初值为0(刚开始时理发师在睡觉,所以理发师这个资源数⽬为0);4)信号量mutex⽤于互斥,初值为1.关于p,v操作:P操作可以看做是申请⼀个资源,不管这个资源有没有都将这个资源的数⽬减1,如果现在资源数⽬⼩于0,就阻塞。
v操作就是释放资源,先将这个资源的数⽬加1,如果发现这个资源数⽬⼩于等于0,就会唤醒在阻塞队列上的⼀个进程看看PV原语实现:1顾客信号量 = 02理发师信号量 = 03互斥信号量mutex = 1// 椅⼦是理发师和顾客精进程都可以访问的临界区4int空椅⼦数量 = N //所有的椅⼦数量56理发师(线程/进程)7 While(true){ //持续不断地循环8 P(顾客)//试图为⼀位顾客服务,如果没有他就睡觉(进程阻塞)9 P(互斥信号量)//如果有顾客,这时他被叫醒(理发师进程被唤醒),要修改空椅⼦的数量10空椅⼦数量++ //⼀张椅⼦空了出来11 V(理发师)//现在有⼀个醒着的理发师,理发师准备理发,多个顾客可以竞争理发师互斥量,但是只有⼀个顾客进程可以被唤醒并得到服务12 V(互斥信号量)//释放椅⼦互斥量,使得进店的顾客可以访问椅⼦的数量以决定是否进店等待13/* 理发师在理发 */14}151617顾客(线程/进程)18while(true)19{//持续不断地循环20 P(互斥信号量)//想坐到⼀张椅⼦上21if (空椅⼦数量 > 0)22 { //如果还有空着的椅⼦的话23空椅⼦数量-- //顾客坐到⼀张椅⼦上了24 V(顾客)//通知理发师,有⼀位顾客来了25 V(互斥信号量)//顾客已经坐在椅⼦上等待了,访问椅⼦结束,释放互斥量26 P(理发师)//该这位顾客理发了,如果理发师还在忙,那么他就等着(顾客进程阻塞)27/* 竞争到了理发师则该顾客开始理发 */28 }29else30{//没有空着的椅⼦31 V(互斥信号标)//不要忘记释放被锁定的椅⼦32/* 顾客没有理发就⾛了 */33}34}⾸先是信号量的实现版本:1 #include <stdio.h>2 #include <semaphore.h>3 #include <pthread.h>4#define CHAIRS 356//这个计数器才是共享资源7int waiting=0; //控制变量, ⽤来记录等候理发的顾客数89 sem_t customers; //⽤来记录等候理发的顾客数,并⽤作阻塞理发师进程10 sem_t barbers; //⽤来记录正在等候顾客的理发师数,并⽤作阻塞顾客进程11 sem_t mutex; //⽤于线程互斥1213void cut_hair()14 {15 printf("理发ing\n");16 }1718void sleeping()19 {20 printf("sleeping\n");21 }2223void *barber(void *arg)24 {25while(1){26 sem_wait(&customers); //若⽆顾客,理发师睡眠27 sem_wait(&mutex);28 waiting--;29 printf("理发师:等待顾客-1,还剩%d⼈等待 \n", waiting);30 sem_post(&barbers);31 sem_post(&mutex);32 cut_hair(); //理发ing, 这个时候顾客已经独享理发师了,所以不在临界区3334 sem_wait(&mutex);35if(waiting==0){ //没⼈就长眠去呗36 sem_post(&mutex);37break;38 }39 sem_post(&mutex);40 }41 pthread_exit(NULL);42 }4344void get_cut()45 {46 printf("顾客%u: 理发ing\n",(unsigned int)pthread_self());47 }4849void *customer(void *arg)50 {51 sem_wait(&mutex); //互斥52if(waiting < CHAIRS){ //等候的⼈⽐椅⼦少53 waiting++; //等候的⼈+154 sem_post(&customers); //多了⼀个顾客55 sem_post(&mutex);56 sem_wait(&barbers); //如果没有理发师了,那顾客就在椅⼦上等着57 get_cut();58 }59else{60 printf("顾客%u: 没椅⼦了,⾛⼈ \n", (unsigned int)pthread_self());61 sem_post(&mutex);62 }63 sem_post(&mutex); //如果前⾯没有椅⼦了,就直接⾛了64 pthread_exit(NULL);65 }66676869int main(int argc, char const *argv[])70 {71void * retval;72int res=0;73int i;74 sem_init(&customers, 0, 0); //没有顾客75 sem_init(&barbers, 0, 0); //没有理发师,都在睡觉呢76 sem_init(&mutex, 0, 1); //实现互斥7778 pthread_t bar, cus[6];79 res+=pthread_create(&bar, NULL, barber, NULL);80for(i=0; i<6; i++){81 res+=pthread_create(&cus[i], NULL, customer, NULL);82 }83if(res!=0){84 printf("线程创建失败!\n");85 pthread_exit(NULL);86 }87 printf("线程创建成功\n");88 pthread_join(bar,&retval);89for(i=0; i<6; i++){90 pthread_join(cus[i],&retval);91 }92return0;93 }。
实验五 文件操作答案
实验五文件操作一、实验目的1、掌握文件的建立、打开与关闭和文件的读写操作2、理解文件定位操作3、通过练习理解文件的基本操作二、实验环境1.计算机2.MATLAB7.0集成环境三、实验说明1.熟练操作MATLAB7.0运行环境2.自主编写程序,必要时参考相关资料3.实验前应写出程序大致框架或完整的程序代码4.实验学时:2学时四、实验内容和步骤1.实验内容(1)以读写方式打开二进制格式数据文件,将浮点数X添加到文件末尾,将文件内容以浮点数格式读入变量Z,将文本文件的第二行读入变量H,向文件尾部移动文件指针6个字节。
1.建立一个文档d:\Program Files\MA TLAB704\work\数.txt>> [fid,message]=fopen('d:\Program Files\MATLAB704\work\数.txt','rt') sta=fclose(fid)fid =11message =''sta =0 打开和关闭成功2.将浮点数X添加到文件末尾>> fid=fopen('d:\Program Files\MATLAB704\work\数.txt','a');fwrite(fid,x,'float')sta=fclose(fid);ans =1成功写入x3.将文件内容以浮点数格式读入变量Z>> fid=fopen('d:\Program Files\MATLAB704\work\数.txt','a');[z,count]=fread(fid,inf,'float')sta=fclose(fid)z =[]count =sta =成功读入z4. 向文件尾部移动文件指针6个字节>> fid=fopen('d:\Program Files\MATLAB704\work\数.txt','a');fseek(Fid,6,'cof') sta=fclose(fid); ans =(2)已知sin( 1.7)ln21cos( 1.7)xxyxπ++=++,当x取-3.0、-2.9、-2.8、…、2.8、2.9、3.0时,求各点的函数值。
操作系统课程设计-用多线程同步方法解决睡眠理发师问题(Sleeping-Barber_Problem
课程设计题目用多线程同步方法解决睡眠理发师问题(Sleeping-Barber Problem) 学院计算机科学与技术学院专业软件工程班级姓名指导教师2010 年 6 月28 日课程设计任务书学生姓名:专业班级:指导教师:工作单位:计算机科学与技术学院题目: 用多线程同步方法解决睡眠理发师问题(Sleeping-Barber Problem)初始条件:1.操作系统:Linux2.程序设计语言:C语言3. 设有一个理发师,5把椅子(另外还有一把理发椅),几把椅子可用连续存储单元。
要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1.技术要求:1)为每个理发师/顾客产生一个线程,设计正确的同步算法2)每个顾客进入理发室后,即时显示“Entered”及其线程自定义标识,还同时显示理发室共有几名顾客及其所坐的位置。
3)至少有10个顾客,每人理发至少3秒钟。
4)多个顾客须共享操作函数代码。
2.设计说明书内容要求:1)设计题目与要求2)总的设计思想及系统平台、语言、工具等。
3)数据结构与模块说明(功能与流程图)4)给出用户名、源程序名、目标程序名和源程序及其运行结果。
(要注明存储各个程序及其运行结果的主机IP地址和目录。
)5)运行结果与运行情况(提示: (1)连续存储区可用数组实现。
(2)编译命令可用:cc -lpthread -o 目标文件名源文件名(3)多线程编程方法参见附件。
)3. 调试报告:1) 调试记录2)自我评析和总结上机时间安排:18周一~ 五08:0 -12:00指导教师签名:年月日系主任(或责任教师)签名:年月日目录1设计题目与要求 (4)1.1 设计题目 (4)1.2 设计要求 (4)1.2.1 初始条件 (4)1.2.2 技术要求 (4)2 总体设计思想及开发环境与工具 (4)2.1 总体设计思想 (4)2.2 多线程编程原理 (5)2.2.1 创建一个线程 (5)2.2.2 等待一个线程结束 (5)2.2.3 信号量 (6)2.3 伪码实现 (6)2.4 开发环境与工具 (7)3数据结构与模块说明 (8)3.1 数据结构 (8)3.2程序模块说明 (8)3.2.1主函数模块 (8)3.2.2 理发师模块 (9)3.2.3 顾客模块 (9)4源程序 (10)4.1用户名、源程序名和目标程序名 (10)4.2源程序代码 (11)5运行结果 (14)5.1运行步骤 (14)5.2运行结果 (15)5.2.1 编辑,编译和运行的过程图 (15)5.2.2 错误部分截图 (16)5.2.3 正确运行结果图 (16)6调试记录 (18)6.1调试记录 (18)6.2自我评析和总结 (19)7参考文献 (19)1设计题目与要求1.1 设计题目用多线程同步方法解决睡眠理发师问题(Sleeping-Barber Problem)1.2 设计要求1.2.1 初始条件(1)操作系统:Linux(2)程序设计语言:C语言(3)设有一个理发师,5把椅子(另外还有一把理发椅),几把椅子可用连续存储单元。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机科学与技术学院操作系统实验报告实验题目:理发店问题理发店问题:假设理发店的理发室中有3个理发椅子和3个理发师,有一个可容纳4个顾客坐等理发的沙发。
此外还有一间等候室,可容纳13位顾客等候进入理发室。
顾客如果发现理发店中顾客已满(超过20人),就不进入理发店。
在理发店内,理发师一旦有空就为坐在沙发上等待时间最长的顾客理发,同时空出的沙发让在等候室中等待时间最长的的顾客就坐。
顾客理完发后,可向任何一位理发师付款。
但理发店只有一本现金登记册,在任一时刻只能记录一个顾客的付款。
理发师在没有顾客的时候就坐在理发椅子上睡眠。
理发师的时间就用在理发、收款、睡眠上。
请利用linux系统提供的IPC进程通信机制实验并实现理发店问题的一个解法。
实验目的:进一步研究和实践操作系统中关于并发进程同步与互斥操作的一些经典问题的解法,加深对于非对称性互斥问题有关概念的理解。
观察和体验非对称性互斥问题的并发控制方法。
进一步了解Linux系统中IPC进程同步工具的用法,训练解决对该类问题的实际编程、调试和分析问题的能力。
硬件环境:Inter(R)Core(TM)*******************内存:4GB 硬盘:500G软件环境:XUbuntu-Linux 操作系统Gnome 桌面 2.18.3BASH_VERSION='3.2.33(1)-releasegcc version 4.1.2gedit 2.18.2OpenOffice 2.3实验步骤:1、问题分析:为了解决本实验的同步问题,采用共享内存,信号量,消息队列三种IPC 同步对象处理。
客户程序思想:每一个客户把自己的请求当做一条消息发送到相应的消息队列中去,并通过阻塞等待接收消息的方式来等待理发师最终帮自己理发。
每一个客户先判断sofa 是不是坐满了,如果没有就坐在沙发上等,否者就判断waitroom 是不是坐满了,如果没有,就坐在waitroom 等,只要有一个坐在sofa的客户离开sofa 理发,理发师就会到waitroom 找最先来的客户,让他进入sofa 等待。
理发师程序思想:理发师查看sofa 上有没有人,没有就睡3 秒,然后再一次看有没有人,如果有人,就到沙发请最先来的客户来理发。
账本互斥的实现:Semaphore mutex=1 ;Sofa 队列的长度和wait 队列的长度的实现:在顾客进程中设置两个变量sofa_count,wait_count,分别保存沙发和等候室的顾客数。
2、算法设计说明如下:该解法利用消息队列的每条消息代表每个顾客,将进入等候室的顾客组织到一个队列,将坐入沙发的顾客组织到另一个队列。
理发师从沙发队列请出顾客,空出的沙发位置再从等候室请入顾客进入沙发队列。
三个理发师进程使用相同的程序段上下文,所有顾客使用同一个程序段上下文。
这样可避免产生太多进程,以便节省系统资源。
理发师程序(Barber){建立一个互斥帐本信号量:s_account,初值=1;建立一个同步顾客信号量:s_customer,初值=0;建立沙发消息队列:q_sofa;建立等候室消息队列:q_wait;建立3个理发师进程:b1_pid, b2_pid, b3_pid;每个理发师进程作:while(1){以阻塞方式从沙发队列接收一条消息,如果有消息,则消息出沙发队列(模拟一顾客理发);唤醒顾客进程(让下一顾客坐入沙发)。
用进程休眠一个随机时间模拟理发过程。
理完发,使用帐本信号量记账。
互斥的获取账本记账唤醒用账本理发师者否则没有消息(沙发上无顾客)则理发师进程在沙发队列上睡眠;当沙发队列有消息时被唤醒(有顾客坐入沙发)。
}}顾客程序(customer){while(1){取沙发队列消息数(查沙发上顾客数) ;如果消息数小于4(沙发没座满)以非阻塞方式从等候室队列接收一条消息(查等候室有顾客否),如果有消息将接收到的消息发送到沙发队列(等候室顾客坐入沙发);否则发送一条消息到沙发队列(新来的顾客直接坐入沙发);否则(沙发坐满)取等候室队列消息数(查等候室顾客数) ;如果消息数小于13发送一条消息到等候室队列(等候室没满,新顾客进等候室);否则在顾客同步信号量上睡眠(等候室满暂不接待新顾客);用进程休眠一个随机时间模拟顾客到达的时间间隔。
}}3、开发调试过程:在shell命令行下运行$ make barber customergcc -g -c barber.c ipc.cgcc barber.o ipc.o -o barbergcc -g -c customer.c ipc.cgcc customer.o ipc.o -o customer假设先运行理发师程序:$ ./barber2726号理发师睡眠2728号理发师睡眠2727号理发师睡眠运行$./customer1号新顾客坐入沙发2号新顾客坐入沙发3号新顾客坐入沙发4号新顾客坐入沙发5号新顾客坐入沙发6号新顾客坐入沙发7号新顾客坐入沙发8号新顾客坐入沙发9号新顾客坐入沙发10号新顾客坐入沙发11号新顾客坐入沙发12号新顾客坐入沙发沙发坐满13号顾客在等候室等候13号顾客从等候室坐入沙发沙发坐满14号顾客在等候室等候14号顾客从等候室坐入沙发沙发坐满15号顾客在等候室等候15号顾客从等候室坐入沙发沙发坐满16号顾客在等候室等候16号顾客从等候室坐入沙发17号新顾客坐入沙发沙发坐满18号顾客在等候室等候18号顾客从等候室坐入沙发沙发坐满19号顾客在等候室等候19号顾客从等候室坐入沙发沙发坐满20号顾客在等候室等候20号顾客从等候室坐入沙发沙发坐满21号顾客在等候室等候21号顾客从等候室坐入沙发......在理发师窗体理发师进程被唤醒:2726号理发师为1号顾客理发……2726号理发师收取1号顾客交费2726号理发师睡眠2728号理发师为2号顾客理发……2728号理发师收取2号顾客交费2728号理发师睡眠2727号理发师为3号顾客理发……2726号理发师为4号顾客理发……2727号理发师收取3号顾客交费2727号理发师睡眠2726号理发师收取4号顾客交费2726号理发师睡眠2728号理发师为5号顾客理发……2728号理发师收取5号顾客交费2728号理发师睡眠2727号理发师为6号顾客理发……2726号理发师为7号顾客理发……2727号理发师收取6号顾客交费2727号理发师睡眠2726号理发师收取7号顾客交费2726号理发师睡眠2728号理发师为8号顾客理发……2728号理发师收取8号顾客交费......反之,如果先运行顾客程序:$ ./customer1号新顾客坐入沙发2号新顾客坐入沙发3号新顾客坐入沙发4号新顾客坐入沙发沙发坐满5号顾客在等候室等候沙发坐满6号顾客在等候室等候沙发坐满7号顾客在等候室等候沙发坐满8号顾客在等候室等候沙发坐满9号顾客在等候室等候沙发坐满10号顾客在等候室等候沙发坐满11号顾客在等候室等候沙发坐满12号顾客在等候室等候沙发坐满13号顾客在等候室等候沙发坐满14号顾客在等候室等候沙发坐满15号顾客在等候室等候沙发坐满16号顾客在等候室等候沙发坐满17号顾客在等候室等候等候室满18号顾客没有进入理发店当18号顾客到达时理发店20个位置已满,顾客进程阻塞(假设理发师进程没运行表示三个理发师正坐在3个理发椅上睡觉) 。
再运行理发师程序:$ ./barber运行截图如下:附件:4.7.分析与感悟:首先运行顾客程序的话,顾客程序首先向沙发队列发送消息,然后向等候室队列发送消息,当两个队列都满了之后,该进程会暂停,及停止在顾客同步信号量上。
而随着理发师程序的开始运行,理发师进程会唤醒顾客进程,及在顾客同步信号量上进行up操作,并且从消息队列中接受消息。
反之,若理发师程序先运行,则三个理发师由于无法从沙发队列上接收到消息,而且由于是阻塞式接受,就会阻塞在这个消息队列上,只有当顾客程序运行时,向沙发队列发送消息后理发师进程才会继续。
通过编写这个实验,是我更加熟练了信号量的使用,明白了消息队列的使用方法,进一步了解了Linux系统中IPC进程同步工具的用法。
附件:Ipc.c#include "ipc.h"int get_ipc_id(char *proc_file,key_t key){FILE *pf;int i,j;char line[BUFSZ],colum[BUFSZ];if((pf = fopen(proc_file,"r")) == NULL){perror("Proc file not open");exit(EXIT_FAILURE);}fgets(line, BUFSZ, pf);while(!feof(pf)){i = j = 0;fgets(line, BUFSZ,pf);while(line[i] == ' ') i++;while(line[i] !=' ') colum[j++] = line[i++]; colum[j] = '\0';if(atoi(colum) != key) continue;j=0;while(line[i] == ' ') i++;while(line[i] !=' ') colum[j++] = line[i++]; colum[j] = '\0';i = atoi(colum);fclose(pf);return i;}fclose(pf);return -1;}int down(int sem_id){struct sembuf buf;buf.sem_op = -1;buf.sem_num = 0;buf.sem_flg = SEM_UNDO;if((semop(sem_id,&buf,1)) <0) { perror("down error ");exit(EXIT_FAILURE);}return EXIT_SUCCESS;}int up(int sem_id){struct sembuf buf;buf.sem_op = 1;buf.sem_num = 0;buf.sem_flg = SEM_UNDO;if((semop(sem_id,&buf,1)) <0) { perror("up error ");exit(EXIT_FAILURE);}return EXIT_SUCCESS;}int set_sem(key_t sem_key,int sem_val,int sem_flg){int sem_id;Sem_uns sem_arg;//测试由sem_key 标识的信号灯数组是否已经建立if((sem_id = get_ipc_id("/proc/sysvipc/sem",sem_key)) < 0 ) {//semget 新建一个信号灯,其标号返回到sem_idif((sem_id = semget(sem_key,1,sem_flg)) < 0){perror("semaphore create error");exit(EXIT_FAILURE);}//设置信号灯的初值sem_arg.val = sem_val;if(semctl(sem_id,0,SETV AL,sem_arg) <0){perror("semaphore set error");exit(EXIT_FAILURE);}}return sem_id;}char * set_shm(key_t shm_key,int shm_num,int shm_flg){int i,shm_id;char * shm_buf;//测试由shm_key 标识的共享内存区是否已经建立if((shm_id = get_ipc_id("/proc/sysvipc/shm",shm_key)) < 0 ) {//shmget 新建一个长度为shm_num 字节的共享内存,其标号返回到shm_idif((shm_id = shmget(shm_key,shm_num,shm_flg)) <0){perror("shareMemory set error");exit(EXIT_FAILURE);}//shmat 将由shm_id 标识的共享内存附加给指针shm_buf if((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0){perror("get shareMemory error");exit(EXIT_FAILURE);}for(i=0; i<shm_num; i++) shm_buf[i] = 0; //初始为0}//shm_key 标识的共享内存区已经建立,将由shm_id 标识的共享内存附加给指针shm_bufif((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0){perror("get shareMemory error");exit(EXIT_FAILURE);}return shm_buf;}int set_msq(key_t msq_key,int msq_flg){int msq_id;//测试由msq_key 标识的消息队列是否已经建立if((msq_id = get_ipc_id("/proc/sysvipc/msg",msq_key)) < 0 ) {//msgget 新建一个消息队列,其标号返回到msq_idif((msq_id = msgget(msq_key,msq_flg)) < 0) {perror("messageQueue set error");exit(EXIT_FAILURE);}}return msq_id;}Ipc.h:#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/sem.h>#include <sys/msg.h>#define BUFSZ 256#define MAXV AL 100#define STRSIZ 8#define WRITERQUEST 1#define READERQUEST 2#define FINISHED 3//写请求标识//读请求标识//读写完成标识typedef union semuns { int val;} Sem_uns;typedef struct msgbuf { long mtype;int mid;} Msg_buf;//信号量key_t costomer_key; int costomer_sem;key_t account_key;int account_sem;int sem_val;int sem_flg;//消息队列int wait_quest_flg;key_t wait_quest_key;int wait_quest_id;int wait_respond_flg;key_t wait_respond_key;int wait_respond_id;int sofa_quest_flg;key_t sofa_quest_key;int sofa_quest_id;int sofa_respond_flg;key_t sofa_respond_key;int sofa_respond_id;int get_ipc_id(char *proc_file,key_t key);char *set_shm(key_t shm_key,int shm_num,int shm_flag); int set_msq(key_t msq_key,int msq_flag);int set_sem(key_t sem_key,int sem_val,int sem_flag);int down(int sem_id);int up(int sem_id);Barber.c:#include "ipc.h"int main(int argc,char *argv[]){// int i;int rate;Msg_buf msg_arg;//可在在命令行第一参数指定一个进程睡眠秒数,以调解进程执行速度if(argv[1] != NULL) rate = atoi(argv[1]);else rate = 3;//联系一个请求消息队列wait_quest_flg = IPC_CREAT| 0644;wait_quest_key = 101;wait_quest_id = set_msq(wait_quest_key,wait_quest_flg);//联系一个响应消息队列wait_respond_flg = IPC_CREAT| 0644;wait_respond_key = 102;wait_respond_id = set_msq(wait_respond_key,wait_respond_flg);//联系一个请求消息队列sofa_quest_flg = IPC_CREAT| 0644;sofa_quest_key = 201;sofa_quest_id = set_msq(sofa_quest_key,sofa_quest_flg);//联系一个响应消息队列sofa_respond_flg = IPC_CREAT| 0644;sofa_respond_key = 202;sofa_respond_id = set_msq(sofa_respond_key,sofa_respond_flg);//信号量使用的变量costomer_key = 301;//顾客同步信号灯键值account_key = 302;//账簿互斥信号灯键值sem_flg = IPC_CREAT | 0644;//顾客同步信号灯初值设为0sem_val = 0;//获取顾客同步信号灯,引用标识存costomer_semcostomer_sem = set_sem(costomer_key,sem_val,sem_flg);//账簿互斥信号灯初值设为1sem_val = 1;//获取消费者同步信号灯,引用标识存cons_semaccount_sem = set_sem(account_key,sem_val,sem_flg);int pid1, pid2;pid1=fork();if(pid1==0) {while(1) {// wait_quest_flg=IPC_NOW AIT;printf("%d号理发师睡眠\n", getpid());wait_quest_flg=0;if(msgrcv(sofa_quest_id, &msg_arg, sizeof(msg_arg), 0, wait_quest_flg)>=0) {msgsnd(sofa_respond_id, &msg_arg,sizeof(msg_arg), 0);printf("%d号理发师为%d号顾客理发……\n", getpid(), msg_arg.mid);sleep(rate);down(account_sem);printf("%d号理发师收取%d号顾客交费\n", getpid(), msg_arg.mid);up(account_sem);}}} else {pid2=fork();if(pid2==0) {while(1) {// wait_quest_flg=IPC_NOW AIT;printf("%d号理发师睡眠\n", getpid());wait_quest_flg=0;if(msgrcv(sofa_quest_id, &msg_arg, sizeof(msg_arg), 0, wait_quest_flg)>=0) {msgsnd(sofa_respond_id,&msg_arg,sizeof(msg_arg), 0);printf("%d号理发师为%d号顾客理发……\n", getpid(), msg_arg.mid);sleep(rate);down(account_sem);printf("%d号理发师收取%d号顾客交费\n", getpid(), msg_arg.mid);up(account_sem);} else {printf("%d号理发师睡眠\n", getpid());}}} else {while(1) {// wait_quest_flg=IPC_NOW AIT;printf("%d号理发师睡眠\n", getpid());wait_quest_flg=0;if(msgrcv(sofa_quest_id, &msg_arg, sizeof(msg_arg), 0, wait_quest_flg)>=0) {msgsnd(sofa_respond_id,&msg_arg,sizeof(msg_arg), 0);printf("%d号理发师为%d号顾客理发……\n", getpid(), msg_arg.mid);sleep(rate);down(account_sem);printf("%d号理发师收取%d号顾客交费\n", getpid(), msg_arg.mid);up(account_sem);} else {printf("%d号理发师睡眠\n", getpid());}}}}return 0;}Customer.c:#include "ipc.h"int main(int argc,char *argv[]){int rate;Msg_buf msg_arg;//可在在命令行第一参数指定一个进程睡眠秒数,以调解进程执行速度if(argv[1] != NULL) rate = atoi(argv[1]);else rate = 3;//联系一个请求消息队列wait_quest_flg = IPC_CREAT| 0644;wait_quest_key = 101;wait_quest_id = set_msq(wait_quest_key,wait_quest_flg);//联系一个响应消息队列wait_respond_flg = IPC_CREAT| 0644;wait_respond_key = 102;wait_respond_id = set_msq(wait_respond_key,wait_respond_flg);//联系一个请求消息队列sofa_quest_flg = IPC_CREAT| 0644;sofa_quest_key = 201;sofa_quest_id = set_msq(sofa_quest_key,sofa_quest_flg);//联系一个响应消息队列sofa_respond_flg = IPC_CREAT| 0644;sofa_respond_key = 202;sofa_respond_id = set_msq(sofa_respond_key,sofa_respond_flg);//信号量使用的变量costomer_key = 301;//顾客同步信号灯键值account_key = 302;//账簿互斥信号灯键值sem_flg = IPC_CREAT | 0644;//顾客同步信号灯初值设为0sem_val = 0;//获取顾客同步信号灯,引用标识存costomer_semcostomer_sem = set_sem(costomer_key,sem_val,sem_flg);//账簿互斥信号灯初值设为1sem_val = 1;//获取消费者同步信号灯,引用标识存cons_semaccount_sem = set_sem(account_key,sem_val,sem_flg);int sofa_count=0;int wait_count=0;int i=0;// int count=0;while(1) {sleep(rate);// count++;// printf("count = %d ", count);i++;// printf("i = %d ", i);msg_arg.mid = i;if(sofa_count < 4) {if(wait_count != 0) {i--;//阻塞方式接收消息msgrcv(wait_quest_id, &msg_arg, sizeof(msg_arg), 0, 0);printf("mid = %d ", msg_arg.mid);msgsnd(wait_respond_id, &msg_arg,sizeof(msg_arg), 0);printf("%d号顾客从等候室坐入沙发\n", msg_arg.mid);// up(costomer_sem);} else {printf("%d号新顾客坐入沙发\n", i);}sofa_quest_flg=IPC_NOW AIT;if(msgsnd(sofa_quest_id, &msg_arg, sizeof(msg_arg), sofa_quest_flg) >= 0){// sofa_count++;// return 0;}sofa_count++;} else if(wait_count < 13) {printf("沙发坐满,%d号顾客在等候室等候……\n", i);wait_quest_flg = IPC_NOWAIT;msgsnd(wait_quest_id, &msg_arg, sizeof(msg_arg), wait_quest_flg);wait_count++;} else {printf("等候室满,%d顾客没有进入理发店\n", i);// down(costomer_sem);msgrcv(sofa_respond_id, &msg_arg, sizeof(msg_arg), 0, 0);sofa_count--;i--;}sofa_quest_flg=IPC_NOW AIT;if(msgrcv(sofa_respond_id, &msg_arg, sizeof(msg_arg), 0, sofa_quest_flg)>=0){sofa_count--;}wait_quest_flg = IPC_NOW AIT;if(msgrcv(wait_respond_id, &msg_arg, sizeof(msg_arg), 0, wait_quest_flg)>=0) {wait_count--;}}return 0;}。