操作系统课程设计报告.docx
《操作系统课程设计报告.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计报告.docx(27页珍藏版)》请在冰点文库上搜索。
操作系统课程设计报告
计算机学院
课程设计报告
课程名称操作系统课程设计
实验学期2010至2011学年,第1学期
学生姓名
专业班级
学号
指导教师
开课系计算机科学系
操作系统课程组制
《操作系统》课程设计报告
实验题目:
UNIX系统管理实践与进程控制、进程通信实现
设计时间:
2010-12-27至
2011-01-02
一、实验目的与要求
1、掌握基本的同步与互斥算法。
2、学习使用UNIX中基本的同步对象,掌握相关函数的使用方法。
3、了解UNIX中多进程的并发执行机制,实现进程的同步与互斥。
4、查阅相关资料。
5、熟悉各种命令、系统调用与实用程序。
6、按给定功能设计相关程序。
7、撰写课程设计报告。
二、实验内容
桌上有一只盘子,盘子只能放5只水果,每次只能放一只水果或取出一只水果。
爸爸专放苹果,妈妈专放橘子,儿子专等吃盘子中的橘子,女儿专等吃盘子中的苹果。
分别用P,V操作实现他们的协作行为。
三、实验设备与环境:
VirtualBox
四、设计正文(包括分析与设计思路、各模块流程图以及带注释的主要算法源码)
分析与设计思路:
首先确定设计四个信号量,分别为盘子(semid_plate),女儿(semid_daugter),儿子(semid_son)以及一个互斥信号量(semid_mutex);四个进程,分别为母亲(mother),父亲(father),女儿(daugter)以及儿子(son).父母亲相当于生产者,当盘子(容量为五)中不满时,即可放苹果或者橘子(每次只能进行一个进程,由互斥信号量控制),否则挂起等待,直到盘子中不满时;女儿和儿子相当于消费者,当女儿要吃苹果时,首先判断盘子中是否有苹果,若有,则消费,否则挂起等待,直到盘中有苹果时,儿子亦然,先判断盘子中是否有橘子,若有,则消费,否则挂起等待,直到盘中有橘子时。
程序主要分为五个部分:
control,father,mother,daugter以及son。
Control功能是:
当缓冲区已经存在时,可以根据用户要求,对其删除或者保留,以及对信号量的初始化;father的功能:
将苹果放入缓冲区,并将缓冲区可放水果个数(semid_plate)减一,同时唤醒女儿,告诉她,有苹果可吃;mother功能:
将橘子放入缓冲区,并将缓冲区可放水果个数(semid_plate)减一,同时唤醒儿子,告诉他,有橘子可吃;daugter功能:
吃盘中的一个苹果之后,将其对应信号量减一(semid_daugter),吃完之后,盘中可放的水果数加一,表明可再放一个水果;son功能:
吃盘中的一个橘子之后,将其对应信号量减一(semid_son),吃完之后,盘中可放的水果数加一,表明可再放一个水果。
(流程图见各模块中)
模块一:
Control
流程图
#include
#include
#include
#include
#include
#include
#defineSHMKEY9075/*共享存储区的键*/
#defineSEMKEY_SON9085
#defineSEMKEY_DAUGTER9086
#defineSEMKEY_PLATE9087
#defineSEMKEY_MUTEX9088/*信号量数组的键*//*注意:
上面的键在系统中必须唯一*/
#defineBUFF_LEN5/*缓冲区可以存放5个水果*/
#definePRODUCT_LEN32/*每种水果是一个字符串:
<=32字符*/
voidset_sembuf_struct(structsembuf*sem,intsemnum,intsemop,intsemflg)
{
/*设置信号量结构*/
sem->sem_num=semnum;
sem->sem_op=semop;
sem->sem_flg=semflg;
}
main()
{
char*addr,end;
intshmid;
intsemid_plate,semid_son,semid_daugter,semid_mutex;/*信号量id*/
structsembufsem_tmp;
/*开辟共享存储区*/
if((shmid=shmget(SHMKEY,BUFF_LEN*PRODUCT_LEN+2,0777|IPC_CREAT|IPC_EXCL))==-1)
{
if(errno==EEXIST)
{
printf("TheBufferHasExisted!
\n");
printf("DoYouWantToDeleteTheBuffer(Y=yes)?
\n====:
");
scanf("%c",&end);
if(end=='y'||end=='Y')
{
/*共享存储区、信号量并不随程序的结束而被删除,如果我们没删除的话,
可以用ipcs命令查看,用ipcrm删除
*/
/*释放缓冲区*/
shmid=shmget(SHMKEY,BUFF_LEN*PRODUCT_LEN+2,0777);
if(shmctl(shmid,IPC_RMID,0)<0)
perror("shmctl:
");
/*同时释放信号量*/
semid_mutex=semget(SEMKEY_MUTEX,1,0777);
semid_plate=semget(SEMKEY_PLATE,1,0777);
semid_son=semget(SEMKEY_SON,1,0777);
semid_daugter=semget(SEMKEY_DAUGTER,1,0777);
semctl(semid_mutex,0,IPC_RMID);
semctl(semid_plate,0,IPC_RMID);
semctl(semid_son,0,IPC_RMID);
semctl(semid_daugter,0,IPC_RMID);
}
}
else
printf("FailToCreateBuffer!
\n");
return-1;
}
addr=(char*)shmat(shmid,0,0);/*连接缓冲区*/
memset(addr,0,BUFF_LEN*PRODUCT_LEN+2);
shmdt(addr);/*离开缓冲区*/
/*创建4个信号量:
1个用于对缓冲区互斥,3个用于生产者、消费者同步*/
if((semid_mutex=semget(SEMKEY_MUTEX,1,0777|IPC_CREAT|IPC_EXCL))==-1)
{
if(errno==EEXIST)
printf("TheSEMKEY_MUTEXHasExisted!
\n");
else
printf("FailToCreateSEMKEY_MUTEX!
\n");
return-1;
}
if((semid_plate=semget(SEMKEY_PLATE,1,0777|IPC_CREAT|IPC_EXCL))==-1)
{
if(errno==EEXIST)
printf("TheSEMKEY_PLATEHasExisted!
\n");
else
printf("FailToCreateSEMKEY_PLATE!
\n");
return-1;
}
if((semid_son=semget(SEMKEY_SON,1,0777|IPC_CREAT|IPC_EXCL))==-1)
{
if(errno==EEXIST)
printf("TheSEM_SONHasExisted!
\n");
else
printf("FailToCreateSEM_SON!
\n");
return-1;
}
if((semid_daugter=semget(SEMKEY_DAUGTER,1,0777|IPC_CREAT|IPC_EXCL))==-1)
{
if(errno==EEXIST)
printf("TheSEM_DAUGTERHasExisted!
\n");
else
printf("FailToCreateSEM_DAUGTER!
\n");
return-1;
}
/*给信号量赋初值*/
set_sembuf_struct(&sem_tmp,0,BUFF_LEN,0);/*BUFF_LEN*/
semop(semid_plate,&sem_tmp,1);
set_sembuf_struct(&sem_tmp,0,0,0);/*0*/
semop(semid_son,&sem_tmp,1);
set_sembuf_struct(&sem_tmp,0,0,0);/*0*/
semop(semid_daugter,&sem_tmp,1);
set_sembuf_struct(&sem_tmp,0,1,0);/*1*/
semop(semid_mutex,&sem_tmp,1);
return0;
}
模块二:
father
流程图:
/*生产者:
father.c*/
#include
#include
#include
#include
#include
#include
#defineSHMKEY9075/*共享存储区的键*/
#defineSEMKEY_SON9085
#defineSEMKEY_DAUGTER9086
#defineSEMKEY_PLATE9087
#defineSEMKEY_MUTEX9088/*信号量数组的键*//*注意:
上面的键在系统中必须唯一*/
#defineBUFF_LEN5/*缓冲区可以存放5个水果*/
#definePRODUCT_LEN32/*每种水果是一个字符串:
<=32字符*/
/*下面的P,V是对系统调用的简单封装*/
intP(intsemid)
{
structsembufp_buf;
p_buf.sem_num=0;
p_buf.sem_op=-1;
p_buf.sem_flg=0;
if(semop(semid,&p_buf,1)==-1)/*semop参见课件ppt*/
{
perror("p(semid)falsed");
exit
(1);
}
else
return(0);
}
intV(intsemid)
{
structsembufv_buf;/*structsembuf参见课件ppt*/
v_buf.sem_num=0;
v_buf.sem_op=1;
v_buf.sem_flg=0;
if(semop(semid,&v_buf,1)==-1)
{
perror("v(semid)failed");
exit
(1);
}
else
return(0);
}
main()
{
char*p_buffer;/*共享存储区地址*/
unsignedcharin;/*生产者存放产品的指针:
它的值存放在全局缓冲区第一个字节*/
charproduct[128]="apple";/*事实只使用32B,128为了避免屏幕输入超过32*/
intshmid;/*共享存储区id*/
intsemid_plate,semid_son,semid_daugter,semid_mutex;/*信号量集合id*/
shmid=shmget(SHMKEY,BUFF_LEN*PRODUCT_LEN+2,0777);/*连接共享存储区:
2存放in,out的值*/
p_buffer=(char*)shmat(shmid,0,0);/*取共享存储区地址*/
semid_mutex=semget(SEMKEY_MUTEX,1,0777);/*获取全局信号量id*/
semid_plate=semget(SEMKEY_PLATE,1,0777);
semid_son=semget(SEMKEY_SON,1,0777);
semid_daugter=semget(SEMKEY_DAUGTER,1,0777);
/*进入临界区*/
P(semid_plate);/*对私有信号量作P操作*/
P(semid_mutex);/*对公有信号量作P操作*//*二者顺序不能换*/
printf("Fatherputanapple\n");
in=(unsignedchar)(*p_buffer);
strncpy(p_buffer+2+in*PRODUCT_LEN,product,PRODUCT_LEN);
in=(in+1)%BUFF_LEN;
*p_buffer=(char)in;
shmdt(p_buffer);/*离开缓冲区*/
/*离开临界区*/
V(semid_daugter);
V(semid_mutex);
}
模块三:
mother
流程图:
/*生产者:
mother.c*/
#include
#include
#include
#include
#include
#include
#defineSHMKEY9075/*共享存储区的键*/
#defineSEMKEY_SON9085
#defineSEMKEY_DAUGTER9086
#defineSEMKEY_PLATE9087
#defineSEMKEY_MUTEX9088/*信号量数组的键*//*注意:
上面的键在系统中必须唯一*/
#defineBUFF_LEN5/*缓冲区可以存放5个水果*/
#definePRODUCT_LEN32/*每种水果是一个字符串:
<=32字符*/
/*下面的P,V是对系统调用的简单封装*/
intP(intsemid)
{
structsembufp_buf;
p_buf.sem_num=0;
p_buf.sem_op=-1;
p_buf.sem_flg=0;
if(semop(semid,&p_buf,1)==-1)/*semop参见课件ppt*/
{
perror("p(semid)falsed");
exit
(1);
}
else
return(0);
}
intV(intsemid)
{
structsembufv_buf;/*structsembuf参见课件ppt*/
v_buf.sem_num=0;
v_buf.sem_op=1;
v_buf.sem_flg=0;
if(semop(semid,&v_buf,1)==-1)
{
perror("v(semid)failed");
exit
(1);
}
else
return(0);
}
main()
{
char*p_buffer;/*共享存储区地址*/
unsignedcharin;/*生产者存放产品的指针:
它的值存放在全局缓冲区第一个字节*/
charproduct[128]="orange";/*事实只使用32B,128为了避免屏幕输入超过32*/
intshmid;/*共享存储区id*/
intsemid_plate,semid_son,semid_daugter,semid_mutex;/*信号量集合id*/
shmid=shmget(SHMKEY,BUFF_LEN*PRODUCT_LEN+2,0777);/*连接共享存储区:
2存放in,out的值*/
p_buffer=(char*)shmat(shmid,0,0);/*取共享存储区地址*/
semid_mutex=semget(SEMKEY_MUTEX,1,0777);/*获取全局信号量id*/
semid_plate=semget(SEMKEY_PLATE,1,0777);
semid_son=semget(SEMKEY_SON,1,0777);
semid_daugter=semget(SEMKEY_DAUGTER,1,0777);
/*进入临界区*/
P(semid_plate);/*对私有信号量作P操作*/
P(semid_mutex);/*对公有信号量作P操作*//*二者顺序不能换*/
printf("Motherputanorange\n");
in=(unsignedchar)(*p_buffer);
strncpy(p_buffer+2+in*PRODUCT_LEN,product,PRODUCT_LEN);
in=(in+1)%BUFF_LEN;
*p_buffer=(char)in;
shmdt(p_buffer);/*离开缓冲区*/
/*离开临界区*/
V(semid_son);
V(semid_mutex);
}
模块四:
daugter
流程图:
/*消费者:
daugter.c*/
#include
#include
#include
#include
#include
#include
#defineSHMKEY9075/*共享存储区的键*/
#defineSEMKEY_SON9085
#defineSEMKEY_DAUGTER9086
#defineSEMKEY_PLATE9087
#defineSEMKEY_MUTEX9088/*信号量数组的键*//*注意:
上面的键在系统中必须唯一*/
#defineBUFF_LEN5/*缓冲区可以存放5个水果*/
#definePRODUCT_LEN32/*每种水果是一个字符串:
<=32字符*/
/*下面的P,V是对系统调用的简单封装*/
intP(intsemid)
{
structsembufp_buf;/*structsembuf参见课件ppt*/
p_buf.sem_num=0;
p_buf.sem_op=-1;
p_buf.sem_flg=0;
if(semop(semid,&p_buf,1)==-1)/*semop参见课件ppt*/
{
perror("p(semid)falsed");
exit
(1);
}
else
return(0);
}
intV(intsemid)
{
structsembufv_buf;
v_buf.sem_num=0;
v_buf.sem_op=1;
v_buf.sem_flg=0;
if(semop(semid,&v_buf,1)==-1)
{
perror("v(semid)failed");
exit
(1);
}
else
return(0);
}
main()
{
char*p_buffer;/*共享存储区地址*/
unsignedcharout;/*消费者取出产品的指针:
它的值存放在全局缓冲区第二个字节*/
charproduct[33];/*它的数据从缓冲区中取*/
intshmid;/*共享存储区id*/
intsemid_plate,semid_son,semid_daugter,semid_mutex;/*信号量集合id*/
shmid=shmget(SHMKEY,BUFF_LEN*PRODUCT_LEN+2,0777);/*连接共享存储区:
2存放in,out的值*/
p_buffer=(char*)shmat(shmid,0,0);/*取共享存储区地址*/
semid_mutex=semget(SEMKEY_MUTEX,1,0777);/*获取全局信号量id*/
semid_plate=semget(SEMKEY_PLATE,1,0777);
semid_son=semget(SEMKEY_SON,1,0777);
semid_daugter=semget(SEMKEY_DAUGTER,1,0777);
/*进入临界区*/
P(semid_daugter);/*对私有信号量作P操作*/
P(semid_mutex);/*对公有信号量作P操作*//*二者顺序不能换*/
out=(unsignedchar)(*p_buffer);
strcpy(product,p_buffer+1+out*PRODUCT_LEN);
out=(out+1)%BUFF_LEN;
*p_buffer=(char)out;
p_buffer--;
shmdt(p_buffer);/*离开缓冲区*/
/*离开临界区*/
V(semid_plate);
V(semid_mutex);
/*吃掉水果:
在屏幕上输出*/
printf("Daugtereatsanapple\n");
}
模块五:
son
流程图:
/*消费者:
son.c*/
#include
#include
#include
#include
#include
#include
#d