操作系统实验四--同步机构
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验四同步机构
一、实验内容
模拟实现用同步机构避免并发进程执行时可能出现的与时间有关的错误。
二、实验目的
进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把如干个进程都能进行访问和修改地那些变量成为公共变量。
由于进程是并发执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后,所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实验要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
三、实验题目
模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
四、实验步骤
(1)程序中使用的数据结构及符号说明
struct spcb
{
char name;//进程名字
char state;//进程状态
char why;//等待原因
int dd ;//断点
};
typedef struct spcb pcb;
pcb producter,consumer,*process,*process1;//各个进程控制块
int s1,s2,i,j,in,out,pc,m;
char array[10];
char c,x;
int pa[6],sa[6];
(2)流程图
初始化程序:模拟实验的程序从初始化程序入口启动,初始化工作包括对信号量S1、S2赋初值,对生产者、消费者进程的PCB初始化。
初始化后转向处理器调度程序,其流程如图1:
图 1 :初始化流程
处理器调度程序:在计算机系统中,进程并发执行时,任一进程占用处理器执行完一条指令后就有可能被打断而让出处理器由其他进程运行。
故在模拟系统中也类似处理,每当执行一条模拟的指令后,保护当前进程的现场,让它成为非运行状态,由处理器调度程序按随机数再选择一个就绪进程占用处理器运行。
处理器调度程序流程见图2:
图2:处理器调度程序流程
模拟处理器指令执行程序:按“指令计数器”PC之值执行指定的质量,且PC加1指向下一条指令。
模拟处理器指令执行的程序流程见图3和图4:
图3:模拟处理器指令执行
(1)模拟P (S ) (2)模拟V (S )
图 4: 模拟PV 操作的执行
另外,为了使得模拟程序有一个结束条件,在图3中附加了“生产者运行结束”的条件判断,模拟时可以采取人工选择的方法实现。
图4给出了P (S )和V (S )模拟指令执行过程的流程。
(3) 源代码
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> #define NULL 0 struct spcb {
char name;//进程名字 char state;//进程状态 char why;//等待原因 int dd ;//断点 };
typedef struct spcb pcb;
pcb producter,consumer,*process,*process1; int s1,s2,i,j,in,out,pc,m; char array[10];
char c,x;
int pa[6],sa[6];
int p(int s) /* p操作原语*/
{
s=s-1;
if(s<0)
{
p rocess->state='B'; /* B表示阻塞*/
p rocess->why='s';
}
else
{
p rocess->state='W'; /* W表示就绪*/
}
return(s);
}
int v(int s) /*v操作原语*/
{
s=s+1;
if(s<=0)
{
p rocess1->state='W';
}
process->state='W';
return(s);
}
char RanChar()
{
char arr[10]={'a','b','c','d','e','f','g','h','i','j'};
return arr[abs(rand()%10)];
}
void put()
{
Sleep(1000);
array[in]=RanChar();
in=(in+1)%10;
printf(" product a char is %c!\n ",array[in-1]);
int k = 0;
for(m=0;m<10;m++)
{
i f (array[m]!=' ') {
printf("%c",array[m]);
k = k+1;
}
}
printf("缓冲池中有%d个产品\n",k);
}
void get()
{
Sleep(1000);
x=array[out];
printf("\n%c get a char fron buffer",x);
printf("\n");
array[out]=' ';
out=(out+1)%10;
int k = 0;
for(m=0;m<10;m++)
{
i f (array[m]!=' ') {
printf("%c",array[m]);
k = k+1;
}
}
printf("缓冲池中有%d个产品\n",k);
}
void gotol()
{
pc=0;
}
void nop()
{;}
void disp() /*建立进程显示函数,用于显示当前进程*/
{
printf("\n name \t state \t why \t dd \n");
printf("|%c\t",process->name);
printf("|%c\t",process->state);
printf("|%c\t",process->why);
printf("|%d\t",process->dd);
printf("\n");
}
void init()/*初始化程序*/
{
s1=10;/*s1表示空缓冲区的数量*/
s2=0; /*s2表示满缓冲区的数量*/
='p';/*对生产者进程初始化*/
producter.state='W';
producter.why=' ';
producter.dd=0;
='c';/*对消费者进程初始化*/
consumer.state='W';
consumer.why=' ';
consumer.dd=0;
for(int k=0;k<10;k++)
{
a rray[k] = ' ';
}
}
void bornpa() /*将生产者程序装入pa[]中*/
{
for(i=0;i<=3;i++)
{
p a[i]=i;
}
}
void bornsa()/*将消费者程序装入sa[]中*/
{
for(i=0;i<=3;i++)
{
s a[i]=i;
}
}
void diaodu()/*处理器调度程序*/
{
while((producter.state=='W')||(consumer.state=='W'))
{
x=rand();/*x随机获得一个数*/
x=x%2;/*对X取于*/
i f(x==0)/*若X等于零,则执行生产者进程,反之执行消费者进程*/
{
process=&producter;/*process表示现行进程,将现行进程置为生产者进程*/
process1=&consumer;
}
e lse
{
process=&consumer;
process1=&producter;
}
p c=process->dd;
i=pc;/*此时把PC的值付给I*/
i f((process->name=='p')&&(process->state=='W'))
{
j=pa[i];
pc=i+1;
switch(j)
{
case 0: s1=p(s1);process->dd=pc;break;
case 1: put();process->state='W';process->dd=pc;break;
case 2: s2=v(s2);process->dd=pc;break;
case 3: gotol();process->state='W';process->dd=pc;
}
}
e lse if((process->name=='c')&&(process->state=='W'))/*执行消费者进程且该进程处于就绪状态*/
{
process->state='W';
j=sa[i];
pc=i+1;
switch(j)
{
case 0: s2=p(s2);process->dd=pc;break;/*申请资源,若没有申请到则跳转*/
case 1: get();process->dd=pc;break;
case 2: s1=v(s1);process->dd=pc;break;
case 3: gotol();process->state='W';process->dd=pc;
}
} /*end else*/
}/*end while*/
printf("\nThe program is over!\n");
}
void main()
{
init();
bornpa();
bornsa();
diaodu();
}
五、实验总结
信号量(semaphore)和P、V操作的同步机构可以有效地解决临界区的问题,使用信号控制相互合作的进程。
当进程检测到信号后,就被迫停止在摸个地方,直到收到专门的信号才能继续执行。
在这个实验里面,要考虑两种错误的情况:1、生产者不可以向已经满了的缓冲区里面添加产品;2、消费者不能从空了的缓冲区里面取产品。
通过这个实验,可以帮助我们很好的理解进程同步的问题,要解决进程同步需要做哪些工作,如何利用信号量机制来解决进程同步问题等等,这些问题其实我们在学习理论知识时都是很少思考的,因为感触不深,所以学了一遍就过去了,但是在自己做实验时才会发现哪些地方是我们需要考虑的,哪些地方是需要注意的,实验给了我们实践的机会,给了我们理论结合实际的机会,从实验中可以学到很多东西,不仅仅是书本上的东西这么简单,更重要的是对待事情严谨的态度。