资源描述
集美大学计算机工程学院实验报告
课程名称:操作系统
班级:
实验成绩:
指导教师:罗冬梅
姓名:
实验项目名称:进程与线程
学号:
上机实践日期:
实验项目编号:实验五
组号:
上机实践时间: 学时
一、目的(本次实验所涉及并要求掌握的知识点)
1.了解线程和进程的概念
2.掌握线程和进程在组成成分上的差别及相关的通讯方式和应用目标
3.fork()函数的使用方法及相关知识
4.系统函数clone()的调用,与父子进程之间的共享存储空间的判断
二、实验内容与设计思想(设计思路、主要数据结构、主要代码结构、主要代码段分析、电路图)
1.用pipe()创建一个管道文件,然后用fork()创建两个生产者和两个消费者进程,它们之间通过pipe()传递信息。
三、实验使用环境(本次实验所使用的平台和相关软件)
Linux虚拟机 vi编辑器
四、实验步骤和调试过程(实验步骤、测试数据设计、测试结果分析)
*****************************实验代码**************************************
#include"sched.h"
#include"pthread.h"
#include"stdio.h"
#include"stdlib.h"
#include"semaphore.h"
int producer(int args); //生产者进程
int consumer(int args);//消费者进程
pthread_mutex_t mutex; //锁
sem_t product; //信号量的类型:产品
sem_t warehouse; //信号量的类型:盒子(即共享的内存空间)
char buffer[8][4];
int bp=0;
main(int argc,char *argv)
{
pthread_mutex_init(&mutex,NULL);///初始化
sem_init(&product,0,0);//初始化产品的数量为0
sem_init(&warehouse,0,8);///初始化共享内存的值为8
int clone_flag,arg,retval;
char *stack;//指向轻进程所用的栈的指针
clone_flag=CLONE_VM|CLONE_SIGHAND|CLONE_FS|CLONE_FILES;
int i;
for(i=0;i<2;i++)
{
arg=i;
stack=(char*)malloc(4096);
retval=clone((void *)producer,&(stack[4095]),clone_flag,arg);
stack=(char *)malloc(4096);
retval=clone((void *)consumer,&(stack[4095]),clone_flag,arg);
}
exit(1);
}
int producer(int args)
{
int id=args;
int i;
for(i=0;i<10;i++)
{
sleep(i+1);
sem_wait(&warehouse);
pthread_mutex_lock(&mutex);
if(id==0)
strcpy(buffer[bp],"aaa\0");
else
strcpy(buffer[bp],"bbb\0");
bp++;
printf("producer %d produce %s in %d \n",id,buffer[bp-1],bp-1);
pthread_mutex_unlock(&mutex);
sem_post(&product);
}
printf("producer%d is over!\n",id);
}
int consumer(int args)
{
int id=args;
int i;
for(i=0;i<10;i++)
{
sleep(10-i);
sem_wait(&product);
pthread_mutex_lock(&mutex);
bp--;
printf("consumer %d get %s in %d \n",id,buffer[bp],bp);
strcpy(buffer[bp],"zzz\0");
pthread_mutex_unlock(&mutex);
sem_post(&warehouse);
}
printf("consumer %d is over!\n",id);
}
****************************************************************************
调试过程:
直接编译书本上的代码:
调试发现CLONE_SIGNAHD的值有误,随后查阅相关资料找出正确拼写:CLONE_SIGHAND
修改后运行结果出错如下:
通过网上搜索出错信息寻得解决方案即:编译时要输入参数 –pthread
结果不正确,返回原代码查看:更改如下:
结果中仍还有错:
根据分析得出,clone的第4个参数未成功传递到函数producer和consumer中,修改clone的第4个参数:
运行第一次:
运行第二次:
由此可知进程间存在并发性
************************************实验分析********************************
信号量 :product 初始量为0
warehouse 初始量为8
生产者进程和消费者进程间共享warehouse,对于同种资源的管理,申请时执行一P次操作,归还时执行一次V操作;
产品的初始值为0可实现进程间简单的同步;
当进程要使用共享资源warehouse时,使用前加锁,防止其他进程进入共享空间,离开共享空间时,将其解锁,是其他进程可使用共享资源。
生产者的活动: 消费者的活动:
P1: P2:
P(warehouse) P(produce)
加锁 加锁
放产品 取产品
解锁 解锁
V(produce) V(warehouse)
生产者:按照盒子的从小到大的编号依次存放产品,并将编号++
00
消费者依次从编号最大的非空的盒子中取产品,并将编号—
这样实现了,生产者和消费者进程间的关系。
五、实验小结(实验中遇到的问题及解决过程、实验中产生的错误及原因分析、实验体会和
编译时根据提示来解决相关的问题,关于宏定义CLONE_SIGHAND的错误和编译时要输入的参数,通过查阅相关的资料即可获知解决方案,对于程序中出现的问题比较难于解决。
通过观察结果,可以分析出现错误的地方可能在哪?
1.输出的结果中,有些盒子上还未有产品(生产者还未放或已取完),而消费者居然可取的产品?
分析,通过回归源代码,发现其工作原路是,生产者在放产品之后,将盒子(warehouse)的编号bp++,所以bp编号的其实是非空盒子的编号加一,及bp编号的盒子是编号最大地非空盒子的下一个盒子(盒子的编号从小到大),所以在输出生产者在哪个盒子放了什么产品时要注意(课本源代码此处有误)。而消费者取产品时与生产者相反,消费者则是从编号最大的盒子往编号小的盒子方向中有序的取产品(如果盒子的编号从左到右从小到大的顺序增大,那么消费者是从左到右,往空盒子中依次放产品,而消费者则是从右到左非空盒子中依次取产品),每取完一次产品,bp—(课本源代码此处有误)
2. 这些解决完后,发现生产者和消费者的代号一直都不会变,,生产者一直为1,生产者放的产品也一成不变为bbb,消费者也一直为1,取的产品也有误?
可能是参数没有传递进来,通过观察其传递进来的参数,并将其修改,即可。
这个程序中,通过对程序的调试,发现问题,解决问题,总结问题,让我对于进程与进程间的通讯和共享空间及它们之间的互斥有了进一步的了解。
六、附录(参考文献和相关资料)
展开阅读全文