
操作系统:实验二 进程的同步与互斥实验报告
高深
操作系统进程同步与互斥实验报告0204192337
包括实验目的、要求,实验内容,实验环境以及实验步骤、过程。
操作系统实验报告——进程同步与互斥
互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
进程的同步与互斥实验
进程的同步互斥实验实验目的1、进一步认识并发执行的实质2、分析进程竞争资源的现象,学习解决进程同步互斥的方法实验内容1、编写程序,使用相关函数实现父子进程对共享文件的同步互斥访问。
2、修改程序,观察对临界资源访问的互斥控制的作用。
实验基础一、临界资源的互斥访问为了实现多进程对临界资源的互斥访问,一个进程访问临界资源的典型程序段类似如下形式:{……….进入区临界区;退出区其余代码;………其中,进入区中判断资源是否可用,如果可用,则资源数量减1,进程进入临界区;否则进程阻塞等待。
退出区中资源数量加1,唤醒阻塞等待该资源的进程。
进入区和退出区都是原子操作。
操作系统中,通常用信号量来实现进入区和退出区,即P操作和V操作。
为了实现用户程序中对某些资源的同步互斥访问,操作系统也提供了一些函数接口,功能类似于对特定临界区的进入区和退出区功能。
二、相关的系统调用(1)lockf(files,function,size):用作锁定文件的某些段或者整个文件。
函数原型:#includeintlockf(intfiles,intfunction;longsize)其中:files是文件描述符;参数function可以取以下值:F_LOCK:锁定一个区域。
F_ULOCK:解除锁定。
参数size指明了从文件当前位置开始的一段连续锁定区域的长度,当size为0时,锁定记录将由当前位置一直扩展到文件尾。
如果lockf的参数function取值为F_LOCK,而指定文件的对应区域已被
求代码~操作系统 进程管理实验 语言C++ 要求如下:
四、实验思路和设计1、进程管理(1)程序流程图由学生自行完成。
(2)主要程序代码\\\/\\\/PCB结构体struct pcb{ int id; \\\/\\\/进程序号 int ra; \\\/\\\/所需资源A的数量 int rb; \\\/\\\/所需资源B的数量 int rc; \\\/\\\/所需资源C的数量 int ntime; \\\/\\\/所需的时间片个数 int rtime; \\\/\\\/已经运行的时间片个数 char state; \\\/\\\/进程状态 struct pcb *next; } *hready=NULL,*hblock=NULL,*p; \\\/\\\/hready,hblock分别为指向就绪和阻塞队列typedef struct pcb PCB;int m,n,r,a,b,c,h=0,i=1,time1Inteval; \\\/\\\/m为要模拟的进程个数,n为初始化进程个数\\\/\\\/r为可随机产生的进程数(r=m-n)\\\/\\\/a,b,c分别为A,B,C三类资源的总量\\\/\\\/i为进城计数,i=1…n\\\/\\\/h为运行的时间片次数,time1Inteval为时间片大小(毫秒)\\\/\\\/建立一个PCB结构体型的空链表PCB *increat(void){ PCB *head; head=NULL; return(head);}\\\/\\\/从链表起始地址开始输出该链表的内容void disp(PCB *head){PCB *p1; p1=head; AnsiString str2; if(head!=NULL) \\\/\\\/链表非空 { do { str2+= ; str2+=IntToStr(p1->id);str2+= ; str2+=(p1->state);str2+= ; str2+=IntToStr(p1->ra);str2+= ; str2+=IntToStr(p1->rb);str2+= ; str2+=IntToStr(p1->rc);str2+= ; str2+=IntToStr(p1->ntime);str2+= ; str2+=IntToStr(p1->rtime);str2+=\\\\r\\\ ; p1=p1->next; }while(p1!=NULL); \\\/\\\/不断输出进程的信息,直到链尾
} \\\/\\\/if else { str2+=\\\\\\该 队 列 中 没 有 进 程
\\\\r\\\ ;} Form1->Memo1->Lines->Add(str2); }\\\/\\\/将进程插入到链尾(包括就绪队列和阻塞队列)PCB *insert(PCB *head,PCB*pcb) \\\/\\\/带两个指针形参:队列指针和当前进程PCB{PCB *pi,*p1;p1=head;pi=pcb;if (head==NULL){head=pi;pi->next=NULL;}else{while(p1->next!=NULL){p1=p1->next;}p1->next=pi;pi->next=NULL;}return(head);}\\\/\\\/对进程进行初始化,建立就绪队阻塞队列。
void input(){AnsiString str1;m=StrToInt (Form1->Edit1->Text); \\\/\\\/读取要模拟的进程总数给mn=StrToInt (Form1->Edit2->Text); \\\/\\\/读取需初始化进程数给na=StrToInt (Form1->Edit3->Text); \\\/\\\/读取A类资源的总数给ab=StrToInt (Form1->Edit4->Text); \\\/\\\/读取B类资源的总数给bc=StrToInt (Form1->Edit5->Text); \\\/\\\/读取C类资源的总数给ctime1Inteval=StrToInt(Form1->Edit6->Text); \\\/\\\/读取时间片长度给time1IntevalForm1->Timer1->Interval=time1Inteval;r=m-n; \\\/\\\/计算可随机产生的进程数为rfor(i=1;i<=n;i++) \\\/\\\/初始化n个进程信息{ p=getpcb(PCB); \\\/\\\/ #define getpcb(type) (type*)malloc(sizeof(type)) p->id=i; str1+= 产生进程ID:;str1+=IntToStr(p->id);str1+=\\\\r\\\ ; p->ra=(random(a-3)+3); str1+= 所需A类资源数:;str1+=IntToStr(p->ra);str1+=\\\\r\\\ ; p->rb=(random(b)); str1+= 所需B类资源数:;str1+=IntToStr(p->ra);str1+=\\\\r\\\ ;p->rc=(random(c-2)+2); str1+= 所需C类资源数:;str1+=IntToStr(p->ra);str1+=\\\\r\\\ ; p->ntime=(random(5)+1); str1+= 所需时间片个数:;str1+=IntToStr(p->ntime);str1+=\\\\r\\\ ; p->rtime=0; p->next=NULL; if (((a-(p->ra))>=0)&&((b-(p->rb))>=0)&&((c-(p->rc))>=0)) \\\/\\\/如果资源符合所需要求 { \\\/\\\/则写入就绪队列队尾a=a-(p->ra); \\\/\\\/当前所剩A类资源数目b=b-(p->rb); \\\/\\\/当前所剩B类资源数目c=c-(p->rc); \\\/\\\/当前所剩C类资源数目p->state='W';hready=insert(hready,p); \\\/\\\/将进程插入就绪队列}\\\/\\\/ifelse \\\/\\\/如果资源不符合所需要求,则写入阻塞队列队尾{p->state='B';hblock=insert(hblock,p);} \\\/\\\/ifstr1+= 当前进程状态:;str1+=(p->state);str1+=\\\\r\\\ ;str1+=\\\\r\\\ ;}\\\/\\\/forForm1->Memo1->Lines->Add(str1);}\\\/\\\/输出就绪队列和阻塞队列的信息void outputall(){AnsiString str1,str2,str3;str3+=\\\\r\\\ ;str3+== = = = = = = = = = = = = = = CPU时间片运行了: ;str3+=IntToStr(h);str3+= 次= = = = = = = = = = = = = = =\\\\r\\\ ;Form1->Memo1->Lines->Add(str3);str1+=*********************************当 前 就 绪 队 列 的 信 息 ;str1+=*********************************\\\\r\\\ ;str1+=进程ID 进程状态 A资源数 B资源数 C资源数 需要时间片 已运行时间片;Form1->Memo1->Lines->Add(str1);disp(hready);str2+=*********************************当 前 阻 塞 队 列 的 信 息;str2+=*********************************\\\\r\\\ ;str2+=\\\\r\\\ ;str2+=进程ID 进程状态 A资源数 B资源数 C资源数 需要时间片 已运行时间片;Form1->Memo1->Lines->Add(str2);disp(hblock);}\\\/\\\/运行就绪队列的头进程,运行一个时间片(FCFS),轮转一个时间片PCB *running(PCB *head){PCB *p1;p1=head;AnsiString str4;If (p1->next==NULL) head=increat();else {head=p1->next; }p1->state='R'; \\\/\\\/进程状态由就绪转向运行(p1->rtime)++; \\\/\\\/已运行时间片数增加1h++;str4+=~~~~~~~~~~~~~~~~ 当前正在运行的进程ID是: ;str4+=IntToStr(p1->id);str4+= ~~~~~~~~~~~~~~~~~~\\\\r\\\ ;str4+=进程ID 进程状态 A资源数 B资源数 C资源数 需要时间片 已运行时间片\\\\r\\\ ;str4+= ;str4+=IntToStr(p1->id);str4+= ;str4+=(p1->state);str4+= ;str4+=IntToStr(p1->ra);str4+= ;str4+=IntToStr(p1->rb);str4+= ;str4+=IntToStr(p1->rc);str4+= ;str4+=IntToStr(p1->ntime);str4+= ;str4+=IntToStr(p1->rtime);str4+= ;Form1->Memo1->Lines->Add(str4);if(p1->ntime==p1->rtime) \\\/\\\/如果已经运行的时间片到达所需次数,该进程结束{ str4+=\\\\r\\\ \\\\r\\\ \\\\\\ID号为:; str4+=IntToStr(p1->id); str4+= 的进程已经完成; Form1->Memo1->Lines->Add(str4); a=a+(p1->ra); b=b+(p1->rb); c=c+(p1->rc); free(p1); \\\/\\\/释放当前指针 }else \\\/\\\/如果已经运行的时间片未到达所需次数,该进程运行一个时间片后进入就绪队列尾 { p1->state='W'; head=insert(head,p1); }return(head);}\\\/\\\/检测当前资源数目是否满足阻塞队列里进程的需求void testblock(){PCB *p1,*p2;p1=hblock;p2=hblock;AnsiString str5;while((hblock!=NULL)&&(p1!=NULL)){if((a-(p1->ra)>=0)&&(b-(p1->rb)>=0)&& (c-(p1->rc)>=0)) \\\/\\\/如果满足{if(p1==hblock){hblock=p1->next;p1->state='W'; hready=insert(hready,p1); \\\/\\\/将阻塞的进程插入就绪队列a=a-(p->ra);b=b-(p->rb);c=c-(p->rc);str5=\\\ID号为: ;str5+=IntToStr(p1->id);str5+= 的进程由阻塞队列转入就绪队列
\\\\r\\\ ; p1=hblock; } \\\/\\\/if(p1==hblock) else {p2->next=p1->next; p1->state='W'; hready=insert(hready,p1); str5=\\\ID号为: ; str5+=IntToStr(p1->id); str5+= 的进程由阻塞队列转入就绪队列
\\\\r\\\ ; p1=p2->next; }\\\/\\\/else } \\\/\\\/大if else {p2=p1; p1=p1->next; } \\\/\\\/else Form1->Memo1->Lines->Add(str5);} \\\/\\\/whlie}\\\/\\\/检测是否有新的进程产生,随机产生新进程void testnew(){int t;AnsiString str6;if(r>0) \\\/\\\/r=m-n为可随机产生的进程数目{t=random(9); \\\/\\\/生成随机数if(t<=7) \\\/\\\/如果随机数小于等于7,则产生新进程,否则不产生{p=getpcb(PCB);str6+=有新的进程申请加入:\\\\r\\\ ;p->id=i++; \\\/\\\/i为全程变量,表示进程号
str6+=进程ID:;str6+=IntToStr(p->id);str6+=\\\\r\\\ ;p->ra=(random(a-3)); \\\/\\\/随机分配资源str6+=所需A类资源数:;str6+=IntToStr(p->ra);str6+=\\\\r\\\ ;p->rb=(random(b-3));str6+=所需B类资源数:;str6+=IntToStr(p->rb);str6+=\\\\r\\\ ;p->rc=(random(c-3));str6+=所需C类资源数:;str6+=IntToStr(p->rc);str6+=\\\\r\\\ ;p->ntime=(random(5)+1); \\\/\\\/随机分配时间片总数str6+=所需时间片个数:;str6+=IntToStr(p->ntime);str6+=\\\\r\\\ ;p->rtime=0; \\\/\\\/已运行时间片数初始为0p->next=NULL;if (((a-(p->ra))>=0)&&((b-(p->rb))>=0)&&((c-(p->rc))>=0)){ \\\/\\\/进程满足要求,进入就绪队列a=a-(p->ra); \\\/\\\/分配资源给该进程,总资源数减少b=b-(p->rb);c=c-(p->rc);p->state='w';str6+=当前进程状态:;str6+=(p->state);str6+=\\\\r\\\ ;hready=insert(hready,p);str6+=资源满足新进程需求,该进程进入就绪队列
;}\\\/\\\/ifelse \\\/\\\/进程不满足要求,进入阻塞队列{p->state='B';hblock=insert(hblock,p);str6+=当前进程状态:;str6+=(p->state);str6+=\\\\r\\\ ;str6+=资源不能满足新进程需求,该进程进入阻塞队列
;}\\\/\\\/else}\\\/\\\/if (t<=7)Form1->Memo1->Lines->Add(str6); }\\\/\\\/if(r>0)r--;}\\\/\\\/系统三类资源变化情况的显示void rescore(){ if(a>a1) {Form1->Edit7->Text=IntToStr(a1);} if(a<0) {Form1->Edit7->Text=0;} if(a>=0&&a
>>>>>>>>>>>>>>;Form1->Memo1->Lines->Add(str);}}\\\/\\\/将结果保存成txt文件void __fastcall TForm1::N8Click(TObject *Sender){ if(Form1->SaveDialog1->Execute()) { FILE* fp=fopen(Form1->SaveDialog1->FileName.c_str(),w); if(fp==NULL) { MessageBox(NULL,打开文件出错,信息,MB_OK); return; } for(int i=0;i
str+=\\\\r\\\ ;}
操作系统课程设计 (包括进程管理、进程的同步和互斥、存储管理)
一、实验的目的与基本要求实验目的本课程设计是为了配合操作系统课程的理论教学而设置的,目的是通过课程设计的综合训练,加强学生对操作系统概念的实际应用技能的训练,提高学生分析问题和解决问题的能力。
基本要求课程设计按照教学要求需要两周时间完成,两周中每天(按每周5天)至少要上3-4小时的机来调试程序。
学生要发挥自主学习的能力,充分利用时间,安排好课设的时间计划,并在课设过程中不断检测自己的计划完成情况,及时的向教师汇报。
课程设计的具体内容如下:设计1 进程管理1. 设计目的加深对进程概念的理解,明确进程和程序的区别;进一步认识并发执行的实质;实现Linux中进程通信的两种方式:软中断和管道通信。
2. 设计内容1) 进程的创建和控制编写一段程序,使用系统调用fork()创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
每个进程在屏幕上显示一个字符,记录屏幕上的显示结果,并分析原因。
修改以编写的程序,将每个进程输出一个字符改为每个进程输出一句话。
2) 进程的软中断通信使用系统调用fork()创建两个子进程,使用系统调用signal()让父进程捕捉用alarm函数设置时钟的时间段终止时产生的信号,当捕捉到该信号后,父进程使用系统调用Kill()向两个子进程发出信号,子进程捕捉到信号后分别输出子进程被杀死信息后终止,父进程等待两个子进程终止后,输出父进程被杀死信息后终止程序。
记录屏幕上的显示结果,并分析原因。
3) 进程的管道通信使用系统调用pipe()建立一个管道;两个子进程分别向管道写信息,父进程则从管道读出来自子进程的信息,显示在屏幕上。
记录屏幕上的显示结果,并分析原因。
3. 系统调用函数说明、参数值及定义1. Fork()创建一个新进程进程int fork()其中返回int取值意义如下:正确返回:在父进程中返回子进程的进程号,在子进程中返回0错误返回:-12. Lockf(int files,int function,long size)用作锁定文件的某些段或者整个文件。
file:文件描述符;function:锁定和解锁,1表示锁定,0表示解锁;size:是锁定或解锁的字节数,若用0,表示从文件的当前位置到文件尾。
3. Signal(int sig, (*func) function)进程控制软中断信号的处理。
signal()会依照参数sig指定的信号编号来设置该信号的处理函数。
sig: SIGALRM: alarm()函数设置的时钟的时间段终止时产生的信号.其它信号略function:信号处理的一个函数地址。
4. kill(int pid,int sig)向一个进程或一个进程组发信号,可以用来送参数sig指定的信号给参数pid指定的进程。
pid: pid>0 将信号传给进程号为pid的进程其它略signumber: 送给进程号为pid进程指定信号量5. alarm(unsigned int seconds)设置一个指定时间的计时器seconds: 设置时间秒数6. int pipe(int filedes[2])filedes为整数数组名,在调用这个函数后,系统为通道分配的两个文件描述符将通过这个数组返回到用户进程中, filedes[1]是文件输出描述符, filedes[0]是文件输入描述符7. int wait(int *status)暂停目前进程的执行,直到有信号到来或子进程的结束。
子进程的结束状态指会由参数status返回,如果不在意结束状态时,则参数status可以设置成NULL设计2 进程的同步与互斥1. 设计目的分析进程争用资源的现象,学习解决进程互斥的方法。
2. 设计内容用程序实现生产者-消费者问题l 问题描述:\\r一个仓库可以存放K件物品。
生产者每生产一件产品,将产品放入仓库,仓库满了就停止生产。
消费者每次从仓库中去一件物品,然后进行消费,仓库空时就停止消费。
l 数据结构:进程:Producer - 生产者进程,Consumer - 消费者进程\\rbuffer: array [0..k-1] of integer;\\rin,out: 0..k-1;\\rin记录第一个空缓冲区,out记录第一个不空的缓冲区\\rs1,s2,mutex: semaphore;\\rs1控制缓冲区不满,s2控制缓冲区不空,mutex保护临界区;\\r初始化s1=k,s2=0,mutex=1l 原语描述producer(生产者进程):\\rItem_Type item;{while (true){produce(&item);p(s1);p(mutex);buffer[in]:=item;\\rin:=(in+1) mod k;v(mutex);v(s2);}}consumer(消费者进程):\\rout:=(out+1) mod k;v(mutex);v(s1);}}设计3 存储管理1. 设计目的通过请求页式存储管理中页面置换算法设计,了解存储技术的特点,掌握请求页式存储管理的页面置换算法。
2. 设计内容l 将指令序列转换为用户虚存中的请求调用页面流。
i. 页面大小为1Kii. 用户内存容量为4页到40页iii. 用户外存的容量为40k在用户外存中,按每K存放10条指令,400条指令在外存中的存放方式为:0-9条指令为第0页10-19条指令为第1页。
390-399条指令为第39页按以上方式,用户指令可组成40页l 通过随机数产生一个指令序列,共400个指令(0-399)l 模拟请求页式存储管理中页面置换算法执行一条指令,首先在外存中查找所对应的页面和页面号,然后将此页面调入内存中,模拟并计算下列各述算法在不同内存容量下的命中率(页面有效次数\\\/页面流的个数)1) 先进先出的算法(FIFO)2) 最久未使用算法(LRU)3. 提示l 随机指令的产生 rand() 或srand()l 用户内存中页面控制结构采用链表 页面控制结构 struct p_str{ int pagenum; \\\/* 页号 *\\\/ int count; \\\/* 访问页面的次数 *\\\/struct p_str next; \\\/* 下一指针 *\\\/}p_str;
如何写操作系统原理的PV原语操作
思路是什么啊
实验二经典的生产者—消费者问题一、目的实现对经典的生产者—消费者问题的模拟,以便更好的理解经典进程同步问题。
二、实验内容及要求编制生产者—消费法,模拟一个生产者、一个消费者,共享一个缓冲池的情形。
1、实现对经典的生产者—消费者问题的模拟,以便更好的理解此经典进程同步问题。
生产者-消费者问题是典型的PV操作问题,假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品。
缓冲池被占用时,任何进程都不能访问。
2、每一个生产者都要把自己生产的产品放入缓冲池,每个消费者从缓冲池中取走产品消费。
在这种情况下,生产者消费者进程同步,因为只有通过互通消息才知道是否能存入产品或者取走产品。
他们之间也存在互斥,即生产者消费者必须互斥访问缓冲池,即不能有两个以上的进程同时进行。
三、生产者和消费者原理分析在同一个进程地址空间内执行两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
消费者线程从缓冲区中获得物品,然后释放缓冲区。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放一个空缓冲区。
当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻挡,直到新的物品被生产出来。
四、生产者与消费者功能描述:生产者功能描述:在同一个进程地址空间内执行两个线程。
生
进程同步问题:司机与售票员 急求怎么写代码啊?
在计算机系统中可以将司机和售票员分别看作P1、P2两个进程,当它们并发地向前推进时,计算机系统所接受到的实际上是司机活动与售票员活动的许多交叉中的任意一个交叉,这些交叉有些满足上述要求,有些则不满足,而操作系统必须保证不发生不满足上述要求的交叉,即: 如P2尚未推进到②处时,而P1已推进到①处,则P1应等待直到P2推进到②处为止; 如P1尚未推进到③时,P2已到④,则P2应等待直到P1推进到③处为止。
P1在①处发生了等待,则P2执行到②处时应将P1唤醒; P2在④处发生了等待,P1到③处应将P2唤醒。
一组相互合作的并发进程,为了协调其推进速度,有时需要相互等待与相互唤醒,进程之间这种相互制约的关系称作进程同步,虽然进程同步仅发生在相互有逻辑关系的进程之间,这种相互制约的关系称作进程同步,进程同步现象仅发生在相互有逻辑关系的进程之间,这点与进程互斥不同,进程互斥现象发生在任意两个进程之间。
与进程同步相关的另一概念是进程合作,一组进程如果它们单独执行不能正常进行,但并发执行可以正常进行,这种现象称为进程合作,参与进程合作的进程称为合作进程,如司机与售票员的例子,二者单独执行都不能正常进行,但二者并发反可以正常进行,成为合作进程,这种进程合作的现象在操作系统中经常发生。
解法一:struct semaphore s1,s2=0,0;cobegin void driver(void) { while(TRUE){ p(s2); 启动车辆; 正常行车; 到站停车; V(s1);} }void conductor(void) { while(TRUE){ 上、下乘客;关车门; V(s2); 售票; P(s1); 开车门;上、下乘客;} }coend解法二:struct semaphore s1,s2=1,0;cobegin void driver(void) { while(TRUE){ P(s2); 启动车辆; 正常行车; 到站停车; V(s1);} }void conductor(void) { while(TRUE){ P(s1); 开车门; 上、下乘客; 关车门; V(s2);售票;} }coend



