操作系统课程设计报告PV操作.docx
《操作系统课程设计报告PV操作.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计报告PV操作.docx(18页珍藏版)》请在冰豆网上搜索。
操作系统课程设计报告PV操作
操作系统设计实验报告
——PV操作
学院:
计算机科学技术与通信工程学院
班级:
计算机0501班
******
学号:
**********
指导老师:
***
2008年1月18日
一、操作系统课程设计题目
LINUX系统管理实践与进程控制、进程通信实现
进程通信题目:
桌上有一只盘子,每次只能放入3只水果。
爸爸专放苹果,妈妈专放橘子,一个儿子专等吃盘子中的橘子,一个女儿专等吃盘子中的苹果。
用P,V操作实现爸爸、妈妈、儿子、女儿进程的同步控制,橘子用orange表示,苹果用apple表示,空用empty表示。
二、开发环境
LINUX环境
三、分析设计
(一)实验原理
1.原理:
parents(包括father和mother)-->|+++|(缓冲区:
存放3个水果)-->daughter和son。
Parents和daughter、son通过共享缓冲区进行通信,信号量用于对缓冲区互斥访问、对parents和daughter、son进行同步。
2.共有五个程序:
control,father,mother,son,daughter.其中control是主控程序.
control:
实现对缓冲区的初始化,要最先执行,且只需要执行一次。
father:
把一个苹果放入缓冲区:
从屏幕输入一个字符串(32字节以内)。
Mother:
把一个橘子放入缓冲区:
从屏幕输入一个字符串(32字节以内)。
Son:
从缓冲区取出一个橘子:
从屏幕上输出一个字符串。
Daughter:
从缓冲区取出一个苹果:
从屏幕上输出一个字符串。
3.注意:
信号量、共享缓冲区都是系统资源,其总个数是有上限的。
每个资源的id在系统中唯一,并且系统不会主动释放它们,所以要小心使用,及时释放。
本程序中:
control在执行一次后(成功执行),信号量、共享缓冲区就会分配。
如果再执行它,control会提示资源已经分配,是否要释放它们?
如果键入y(Y),则资源释放,此后执行father,mother,son,daughter都会报错。
当然也可以使用ipcsipcrm命令来查看或释放资源。
4.为了结构清晰,程序没有多余的输入或输出。
在father,mother,son,daughter程序中适当的位置增加输出语句,和输入字符语句将程序暂停在某个位置,以观察运行的详细进程。
(二)虚拟机下linux挂载U盘
需要让你的虚拟机GuestOS(Linux)能自动识别U盘。
方法如下:
保持焦点在Linux上,插入U盘,这时宿主操作系统Windows会弹出“找到新设备的提示”,然后一步一步的点下一步,结束以后,就可以在linux使用fdisk-l/dev/sdb命令查看到/dev/sdb1。
在虚拟机识别出USB之后,用fdisk-l/dev/sdb或fdisk-l/dev/hdb查看,会看到U盘被识别为sdb1,使用mount命令挂载即可。
先在/mnt建一个新的文件夹,例如usb。
则可通过:
mount-tvfat/dev/sdb1/mnt/usb挂载上U盘
卸载使用:
umount/dev/sdb1
四、源程序
1.主控程序control.c
#include
#include
#include
#include
#include
#include
#defineSHMKEY9075/*共享存储区的键*/
#defineSEMKEY_son9084
#defineSEMKEY_parents9085
#defineSEMKEY_daughter9086
#defineSEMKEY_MUTEX9087/*信号量数组的键*//*注意:
上面的键在系统中必须唯一*/
#defineBUFF_LEN3/*缓冲区可以存放3个产品*/
#definePRODUCT_LEN10/*每个产品是一个字符串:
<=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_parents,semid_daughter,semid_son,semid_mutex;/*信号量id*/
structsembufsem_tmp;
/*开辟共享存储区*/
if((shmid=shmget(SHMKEY,BUFF_LEN*PRODUCT_LEN+4,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+4,0777);
if(shmctl(shmid,IPC_RMID,0)<0)
perror("shmctl:
");
/*同时释放信号量*/
semid_mutex=semget(SEMKEY_MUTEX,1,0777);
semid_daughter=semget(SEMKEY_daughter,1,0777);
semid_parents=semget(SEMKEY_parents,1,0777);
semid_son=semget(SEMKEY_son,1,0777);
semctl(semid_mutex,0,IPC_RMID);
semctl(semid_daughter,0,IPC_RMID);
semctl(semid_parents,0,IPC_RMID);
semctl(semid_son,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);/*离开缓冲区*/
/*创建3个信号量:
1个用于对缓冲区互斥,2个用于生产者、消费者同步*/
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_daughter=semget(SEMKEY_daughter,1,0777|IPC_CREAT|IPC_EXCL))==-1)
{
if(errno==EEXIST)
printf("TheSEMKEY_daughterHasExisted!
\n");
else
printf("FailToCreateSEMKEY_daughter!
\n");
return-1;
}
if((semid_parents=semget(SEMKEY_parents,1,0777|IPC_CREAT|IPC_EXCL))==-1)
{
if(errno==EEXIST)
printf("TheSEM_parentsHasExisted!
\n");
else
printf("FailToCreateSEM_parents!
\n");
return-1;
}
if((semid_son=semget(SEMKEY_son,1,0777|IPC_CREAT|IPC_EXCL))==-1)
{
if(errno==EEXIST)
printf("TheSEMKEY_sonHasExisted!
\n");
else
printf("FailToCreateSEMKEY_son!
\n");
return-1;
}
/*给信号量赋初值*/
set_sembuf_struct(&sem_tmp,0,3,0);/*BUdaughterFF_LEN*/
semop(semid_parents,&sem_tmp,1);
set_sembuf_struct(&sem_tmp,0,0,0);/*0*/
semop(semid_daughter,&sem_tmp,1);
set_sembuf_struct(&sem_tmp,0,0,0);/*0*/
semop(semid_son,&sem_tmp,1);
set_sembuf_struct(&sem_tmp,0,1,0);/*1*/
semop(semid_mutex,&sem_tmp,1);
return0;
}
2.父亲:
father.c
#include
#include
#include
#include
#include
#include
#defineSHMKEY9075/*共享存储区的键*/
#defineSEMKEY_son9084
#defineSEMKEY_parents9085
#defineSEMKEY_daughter9086
#defineSEMKEY_MUTEX9087/*信号量数组的键*//*注意:
上面的键在系统中必须唯一*/
#defineBUFF_LEN3/*缓冲区可以存放3个水果*/
#definePRODUCT_LEN6/*每个产品是一个字符串:
<=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;/*生产者存放产品的指针:
它的值存放在全局缓冲区第一个字节*/
charapple[6];/*事实只使用32B,128为了避免屏幕输入超过32*/
intshmid;/*共享存储区id*/
intsemid_parents,semid_daughter,semid_mutex;/*信号量集合id*/
shmid=shmget(SHMKEY,BUFF_LEN*PRODUCT_LEN+4,0777);/*连接共享存储区:
2存放in,out的值*/
p_buffer=(char*)shmat(shmid,0,0);/*取共享存储区地址*/
semid_mutex=semget(SEMKEY_MUTEX,1,0777);/*获取全局信号量id*/
semid_parents=semget(SEMKEY_parents,1,0777);
semid_daughter=semget(SEMKEY_daughter,1,0777);
/*从屏幕接收产品*/
printf("PleaseProduct(astring,length<=32B):
\n====:
");
gets(apple);/*128的意义在此,此函数不检查字符串长度*/
/*进入临界区*/
P(semid_parents);/*对私有信号量作P操作*/
P(semid_mutex);/*对公有信号量作P操作*//*二者顺序不能换*/
in=(unsignedchar)(*p_buffer);
strncpy(p_buffer+4+in*PRODUCT_LEN,apple,PRODUCT_LEN);
in=(in+1);
*p_buffer=(char)in;
shmdt(p_buffer);/*离开缓冲区*/
/*离开临界区*/
V(semid_daughter);
V(semid_mutex);
}
3.母亲:
mother.c
#include
#include
#include
#include
#include
#include
#defineSHMKEY9075/*共享存储区的键*/
#defineSEMKEY_son9084
#defineSEMKEY_parents9085
#defineSEMKEY_daughter9086
#defineSEMKEY_MUTEX9087/*信号量数组的键*//*注意:
上面的键在系统中必须唯一*/
#defineBUFF_LEN3/*缓冲区可以存放3个水果*/
#definePRODUCT_LEN10/*每个产品是一个字符串:
<=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;/*生产者存放产品的指针:
它的值存放在全局缓冲区第一个字节*/
charorange[6];/*事实只使用32B,128为了避免屏幕输入超过32*/
intshmid;/*共享存储区id*/
intsemid_parents,semid_son,semid_mutex;/*信号量集合id*/
shmid=shmget(SHMKEY,BUFF_LEN*PRODUCT_LEN+4,0777);/*连接共享存储区:
2存放in,out的值*/
p_buffer=(char*)shmat(shmid,0,0);/*取共享存储区地址*/
semid_mutex=semget(SEMKEY_MUTEX,1,0777);/*获取全局信号量id*/
semid_parents=semget(SEMKEY_parents,1,0777);
semid_son=semget(SEMKEY_son,1,0777);
/*从屏幕接收产品*/
printf("PleaseProduct(astring,length<=32B):
\n====:
");
gets(orange);/*128的意义在此,此函数不检查字符串长度*/
/*进入临界区*/
P(semid_parents);/*对私有信号量作P操作*/
P(semid_mutex);/*对公有信号量作P操作*//*二者顺序不能换*/
p_buffer=p_buffer+2;
in=(unsignedchar)(*p_buffer);
strncpy(p_buffer+2+(BUFF_LEN-1)*PRODUCT_LEN-in*PRODUCT_LEN,orange,PRODUCT_LEN);
in=(in+1);
*p_buffer=(char)in;
p_buffer=p_buffer-2;
shmdt(p_buffer);/*离开缓冲区*/
/*离开临界区*/
V(semid_son);
V(semid_mutex);
}
4.女儿:
daughter.c
#include
#include
#include
#include
#include
#include
#defineSHMKEY9075/*共享存储区的键*/
#defineSEMKEY_son9084
#defineSEMKEY_parents9085
#defineSEMKEY_daughter9086
#defineSEMKEY_MUTEX9087/*信号量数组的键*//*注意:
上面的键在系统中必须唯一*/
#defineBUFF_LEN3/*缓冲区可以存放3个水果*/
#definePRODUCT_LEN10/*每个产品是一个字符串:
<=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,in;/*消费者取出产品的指针:
它的值存放在全局缓冲区第二个字节*/
charapple[33];/*它的数据从缓冲区中取*/
intshmid;/*共享存储区id*/
intsemid_parents,semid_daughter,semid_mutex;/*信号量集合id*/
shmid=shmget(SHMKEY,BUFF_LEN*PRODUCT_LEN+4,0777);/*连接共享存储区:
2存放in,out的值*/
p_buffer=(char*)shmat(shmid,0,0);/*取共享存储区地址*/
semid_mutex=semget(SEMKEY_MUTEX,1,0777);/*获取全局信号量id*/
semid_parents=semget(SEMKEY_parents,1,0777);
semid_daughter=semget(SEMKEY_daughter,1,0777);
/*进入临界区*/
P(semid_mutex);/*对私有信号量作P操作*/
P(semid_daughter);/*对公有信号量作P操作*//*二者顺序不能换*/
p_buffer++;
out=(unsignedchar)(*p_buffer);
p_buffer=p_buffer-1;
in=(unsignedchar)(*p_buffer);
strcpy(apple,p_buffer+4+out*PRODUCT_LEN);
if(in==2)
{
strcpy(p_buffer+4+0*PRODUCT_LEN,p_buffer+4+1*PRODUCT_LEN);
}
if(in==3)
{