操作系统课程设计.docx
- 文档编号:5911936
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:14
- 大小:69.01KB
操作系统课程设计.docx
《操作系统课程设计.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计.docx(14页珍藏版)》请在冰豆网上搜索。
操作系统课程设计
操作系统
综合实验说明书
学院:
信息科学与工程学院
班级:
计算机11-3
完成人:
姓名:
赵乐学号:
201101050230
指导教师:
山东科技大学
2013年1月1日课程设计正文
1、课程设计题目:
基于线程的生产者-消费者的合作问题
2、课程设计目的:
在Linux环境下使用POSIX库进行设计实现生产者从外设获取数据进行生产,消费者消费后进行输出,并存储输出结果。
从而使得本学期学习的知识能够充分利用起来,包括使用线程机制、同步互斥机制、I/O技术等
3、课程设计背景知识说明:
1.线程(pthread)
(1).线程创建(pthread_create)
#include
intpthread_create(pthread_t*restrictthread,constpthread_attr_t*restrictattr,void*(*start_routine)(void*),
void*restrictarg);
返回值:
成功返回0,失败返回错误号
进程id的类型是pid_t,每个进程的id在整个系统中是唯一的,pid_t=getpid
(2),是一个正整数值。
线程id的类型是thread_t,它只在当前进程中保证是唯一的,在不同的系统中thread_t这个类型有不同的实现,它可能是一个整数值,也可能是一个结构体,也可能是一个地址,thread_t=pthread_self(3)。
(2).线程终止(pthread_exit)
voidpthread_exit(void*value_ptr);
value_ptr是void*类型,和线程函数返回值的用法一样,其它线程可以调用pthread_join获得这个指针。
(3).线程等待(pthread_join)
intpthread_join(pthread_tthread,void**value_ptr);
返回值:
成功返回0,失败返回错误号
2.互斥锁(Mutex)
(1).初始化(mutex_init)
Mutex用pthread_mutex_t类型的变量表示;
intpthread_mutex_init(pthread_mutex_t*restrictmutex,constpthread_mutexattr_t*restrictattr);
pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;
返回值:
成功返回0,失败返回错误号。
(2).销毁(pthread_mutex_destroy)
intpthread_mutex_destroy(pthread_mutex_t*mutex);
返回值:
成功返回0,失败返回错误号。
(3).加锁和解锁(mutex_lock、mutex_trylock、mutex_unlock)
intpthread_mutex_lock(pthread_mutex_t*mutex);
intpthread_mutex_trylock(pthread_mutex_t*mutex);
intpthread_mutex_unlock(pthread_mutex_t*mutex);
返回值:
成功返回0,失败返回错误号。
一个线程可以调用pthread_mutex_lock获得Mutex,如果这时另一个线程已经调用pthread_mutex_lock获得了该Mutex,则当前线程需要挂起等待,直到另一个线程调用pthread_mutex_unlock释放Mutex,当前线程被唤醒,才能获得该Mutex并继续执行。
3.条件变量(ConditionVariable)
(1).在pthread库中通过条件变量(ConditionVariable)来阻塞等待一个条件,或者唤醒等待这个条件的线程。
ConditionVariable用pthread_cond_t类型的变量表示。
(2).初始化和销毁(pthread_cond_init、pthread_cond_destroy)
intpthread_cond_destroy(pthread_cond_t*cond);
intpthread_cond_init(pthread_cond_t*restrictcond,
constpthread_condattr_t*restrictattr);
pthread_cond_tcond=PTHREAD_COND_INITIALIZER;
返回值:
成功返回0,失败返回错误号。
Mutex的初始化和销毁类似,pthread_cond_init函数初始化一个条件变量,attr参数为NULL则表示缺省属性,pthread_cond_destroy函数销毁一个ConditionVariable。
如果条件变量是静态分配的,也可以用宏定义PTHEAD_COND_INITIALIZER初始化,相当于用pthread_cond_init函数初始化并且attr参数为NULL。
(3).条件的触发(pthread_cond_timedwait)、广播(pthread_cond_broadcast)、等待(pthread_cond_wait)
intpthread_cond_timedwait(pthread_cond_t*restrictcond,
pthread_mutex_t*restrictmutex,conststructtimespec
*restrictabstime);
intpthread_cond_wait(pthread_cond_t*restrictcond,pthread_
mutex_t*restrictmutex);
intpthread_cond_broadcast(pthread_cond_t*cond);
intpthread_cond_signal(pthread_cond_t*cond);
返回值:
成功返回0,失败返回错误号。
4、设计
概要:
通过三组共九个信号量解决线程间的协作和互斥问题。
设计思路:
1通过三组信号量解决互斥问题。
每组信号量控制一个缓存空间。
2.设计一个判断,用于区分不同组的生产者和消费者。
3.设计一个消费平衡机制,尽量平衡消费者的消费意向。
平衡生产者的缓存空间。
4.设计一个判断,用于判定消费者应当退出。
重要代码注释:
1.信号量定义
sem_tempty_sem0;//同步信号量,当满了时阻止生产者放产品第一组
sem_tfull_sem0;//同步信号量,当没产品时阻止消费者消费第一组
pthread_mutex_tmutex0;//互斥信号量一次只有一个线程访问缓冲第一组
sem_tempty_sem1;//同步信号量,当满了时阻止生产者放产品第二组
sem_tfull_sem1;//同步信号量,当没产品时阻止消费者消费第二组
pthread_mutex_tmutex1;//互斥信号量,一次只有一个线程访问缓冲第二组
sem_tempty_sem2;//同步信号量,当满了时阻止生产者放产品第三组
sem_tfull_sem2;//同步信号量,当没产品时阻止消费者消费第三组
pthread_mutex_tmutex2;//互斥信号量,一次只有一个线程访问缓冲第三组
2.
sem_wait(&empty_sem2);//生产者核心代码
pthread_mutex_lock(&mutex2);
in=in%M;
printf("(P2)product%din%d\n",id,in);
buff[2][in]=1;
++in;
pthread_mutex_unlock(&mutex2);
sem_post(&full_sem2);
3.//消费者核心代码
sem_wait(&full_sem0);
pthread_mutex_lock(&mutex0);
out=out%M;
printf("(C0)prochase%din%d\n",id,out);
buff[0][out]=0;
++out;
pthread_mutex_unlock(&mutex0);
sem_post(&empty_sem0);
5、测试
运行结果分析:
6、总结
信号量可以有效的解决互斥问题,在编程过程中需要注意信号量修改的顺序。
程序关于不同生产者处理的细节较易出错。
事实上也是如此,调试阶段对细节进行了大量的修改和优化。
程序调试阶段,多线程的处理上出现较多出错误。
说明我在线程处理的细节上还有待加强。
本程序在10~30号生产者产品的处理上有些仓促。
只是用了一个简单的平衡处理,实际效果一般。
目前未发现不良后果。
有待后续改进。
7、源代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineN30//消费者或者生产者的数目
#defineM20//缓冲数目
#defineD30//生产者生产产品上限
intPn[3]={0};//活动中的生产者
intin=0;//生产者放置产品的位置
intout=0;//消费者取产品的位置
intbuff[3][M]={0};//缓冲初始化为0,开始时没有产品
sem_tempty_sem0;//同步信号量,当满了时阻止生产者放产品第一组
sem_tfull_sem0;//同步信号量,当没产品时阻止消费者消费第一组
pthread_mutex_tmutex0;//互斥信号量一次只有一个线程访问缓冲第一组
sem_tempty_sem1;//同步信号量,当满了时阻止生产者放产品第二组
sem_tfull_sem1;//同步信号量,当没产品时阻止消费者消费第二组
pthread_mutex_tmutex1;//互斥信号量,一次只有一个线程访问缓冲第二组
sem_tempty_sem2;//同步信号量,当满了时阻止生产者放产品第三组
sem_tfull_sem2;//同步信号量,当没产品时阻止消费者消费第三组
pthread_mutex_tmutex2;//互斥信号量,一次只有一个线程访问缓冲第三组
intproduct_id=0;//生产者id
intprochase_id=0;//消费者id
/*生产者方法*/
void*product()
{
intid=++product_id;
if(id>10)
{
Pn[2]++;//生产者+1
inti=D;//产品计数
while(i--)
{
//用sleep的数量可以调节生产和消费的速度,便于观察
sleep
(1);
sem_wait(&empty_sem2);
pthread_mutex_lock(&mutex2);
in=in%M;
printf("(P2)product%din%d\n",id,in);
buff[2][in]=1;
++in;
pthread_mutex_unlock(&mutex2);
sem_post(&full_sem2);
}
Pn[2]--;//生产者完成上限,-1
}
else
{
if(id%2==0)
{
Pn[0]++;
inti=D;
while(i--)
{
//用sleep的数量可以调节生产和消费的速度,便于观察
sleep
(1);
sem_wait(&empty_sem0);
pthread_mutex_lock(&mutex0);
in=in%M;
printf("(P0)product%din%d\n",id,in);
buff[0][in]=1;
++in;
pthread_mutex_unlock(&mutex0);
sem_post(&full_sem0);
}
Pn[0]--;
}
else
{
Pn[1]++;
inti=D;
while(i--)
{
//用sleep的数量可以调节生产和消费的速度,便于观察
sleep
(1);
sem_wait(&empty_sem1);
pthread_mutex_lock(&mutex1);
in=in%M;
printf("(P1)product%din%d\n",id,in);
buff[1][in]=1;
++in;
pthread_mutex_unlock(&mutex1);
sem_post(&full_sem1);
}
Pn[1]--;
}
}
}
/*消费者方法*/
void*prochase()
{
intid=++prochase_id;
if(id%2==0)
{
inti=1,m=-1,n=-1;//消费者消费意向平衡
while
(1)
{
if(i>0)
{i=m*i;
//消费意向转移
//用sleep的数量可以调节生产和消费的速度,便于观察
sleep
(1);
//sleep
(1);
sem_wait(&full_sem0);
pthread_mutex_lock(&mutex0);
out=out%M;
printf("(C0)prochase%din%d\n",id,out);
buff[0][out]=0;
++out;
pthread_mutex_unlock(&mutex0);
sem_post(&empty_sem0);
if(Pn[0]==0)n=1;
//此消费意向作废
}
else
{i=n*i;
//用sleep的数量可以调节生产和消费的速度,便于观察
sleep
(1);
//sleep
(1);
sem_wait(&full_sem2);
pthread_mutex_lock(&mutex2);
out=out%M;
printf("(C1)prochase%din%d\n",id,out);
buff[2][out]=0;
(1);
++out;
pthread_mutex_unlock(&mutex2);
sem_post(&empty_sem2);
if(Pn[2]==0)m=1;
}
if(m==1&&n==1)break;
}
}
else
{
inti=1,m=-1,n=-1;
while
(1)
{
if(i>0)
{
i=m*i;
//用sleep的数量可以调节生产和消费的速度,便于观察
sleep
(1);
//sleep
(1);
sem_wait(&full_sem1);
pthread_mutex_lock(&mutex1);
out=out%M;
printf("(C1)prochase%din%d\n",id,out);
buff[1][out]=0;
++out;
pthread_mutex_unlock(&mutex1);
sem_post(&empty_sem1);
if(Pn[1]==0)n=1;
}
else
{i=n*i;
//用sleep的数量可以调节生产和消费的速度,便于观察
sleep
(1);
sem_wait(&full_sem2);
pthread_mutex_lock(&mutex2);
out=out%M;
printf("(C1)prochase%din%d\n",id,out);
buff[2][out]=0;
++out;
pthread_mutex_unlock(&mutex2);
sem_post(&empty_sem2);
if(Pn[2]==0)
m=1;
}
if(m==1&&n==1)break;
}
}
}
intmain()
{
pthread_tid1[N];
pthread_tid2[N];
inti;
intret[N];
//初始化同步信号量
intini1=sem_init(&empty_sem0,0,M);
intini2=sem_init(&full_sem0,0,0);
intini3=sem_init(&empty_sem1,0,M);
intini4=sem_init(&full_sem1,0,0);
intini5=sem_init(&empty_sem2,0,M);
intini6=sem_init(&full_sem2,0,0);
if(ini1&&ini2&&ini3&&ini4&&ini5&&ini6!
=0)
{
printf("seminitfailed\n");
exit
(1);
}
//初始化互斥信号量
intini7=pthread_mutex_init(&mutex0,NULL);
intini8=pthread_mutex_init(&mutex1,NULL);
intini9=pthread_mutex_init(&mutex2,NULL);
if(ini7&&ini8&&ini9!
=0)
{
printf("mutexinitfailed\n");
exit
(1);
}
//创建N个生产者线程
for(i=0;i { ret[i]=pthread_create(&id1[i],NULL,product,(void*)(&i)); if(ret[i]! =0) { printf("product%dcreationfailed\n",i); exit (1); } } //创建N个消费者线程 for(i=0;i { ret[i]=pthread_create(&id2[i],NULL,prochase,(void*)(&i)); if(ret[i]! =0) { printf("prochase%dcreationfailed\n",i); exit (1); } } //销毁线程 for(i=0;i { pthread_join(id1[i],NULL); pthread_join(id2[i],NULL); } exit(0); }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 课程设计