操作系统课程设计实验报告短学期Word格式文档下载.docx
《操作系统课程设计实验报告短学期Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计实验报告短学期Word格式文档下载.docx(30页珍藏版)》请在冰豆网上搜索。
1
#defineREADY
2
#defineBLOCKED
3
#defineNTCB
100
structTCB
{
unsignedchar
*stack;
/*堆栈的起始地址*/
unsigned
ss;
/*堆栈段址*/
sp;
/*堆栈指针*/
char
state;
/*线程的外部标识符*/
name[10];
/*NTCB是系统允许的最多任务个数*/
structbuffer*mq;
/*消息队列队首指针,初值为NULL*/
structsemaphoremutex;
/*消息队列的互拆信号量,初值为{1,NULL}*/
structsemaphoresm;
/*消息队列的计数信号量,初值为{0,NULL}*/
intreaderNum;
/*当线程作为读线程时所读线程的线程内部标识符*/
}tcb[NTCB];
2、创建线程:
线程创建的一般步骤
1.为新线程分配一个线程控制块,TCB数组的下标即为该线程的内部标识符。
2.为新线程分配私有堆栈空间。
3.初始化新线程的私有堆栈,即按CPU调度时现场信息的保存格式布置堆栈。
4.初始化线程控制块。
5.其它工作。
如按优先级进行CPU调度,则需在TCB中加上优先权信息。
6.返回新线程的内部标识符。
为新线程分配私有堆栈空间
intcreate(char*name,codeptrcode,unsignedstacklen,unsignedprio)
inti;
structint_regs*ir;
for(i=1;
i<
NTCB;
i++)
if(tcb[i].state==FINISHED)
break;
if(i==NTCB)return-1;
strcpy(tcb[i].name,name);
tcb[i].stack=(unsignedchar*)malloc(stacklen);
tcb[i].ss=FP_SEG(tcb[i].stack);
tcb[i].sp=FP_OFF(tcb[i].stack+stacklen);
tcb[i].state=READY;
tcb[i].prio=prio;
*((unsigned*)(tcb[i].sp-2))=FP_SEG(over);
*((unsigned*)(tcb[i].sp-4))=FP_OFF(over);
tcb[i].sp-=(sizeof(structint_regs)+4);
ir=(structint_regs*)tcb[i].sp;
ir->
ds=tcb[i].ss;
es=tcb[i].ss;
ip=FP_OFF(code);
cs=FP_SEG(code);
flags=0x200;
returni;
}
3、撤消线程
1.释放线程的私有堆栈空间。
2.重新进行CPU调度。
voidover()
if(tcb[current].state==RUNNING)
free(tcb[current].stack);
tcb[current].state=FINISHED;
SWITCH();
/*重新进行CPU调度*/
利用时钟中断来进行CPU调度,设计中要注意:
新中断处理程序不能太长,否则系统效率将大大降低甚至使系统无法正常工作;
在新的时钟中断处理程序里必须调用系统原来的INT08H,否则将影响磁盘马达和系统的计时。
voidinterruptSWITCH()
disable();
tcb[current].ss=_SS;
tcb[current].sp=_SP;
if(tcb[current].state==RUNNING)
tcb[current].state=READY;
current=find();
_SS=tcb[current].ss;
_SP=tcb[current].sp;
tcb[current].state=RUNNING;
enable();
voidinterruptnew_int8()
/*调用原来的中断处理程序*/
(*old_int8)();
timecount++;
/*优先级加1*/
tcb[current].prio++;
if(timecount>
=TLE)
disable();
tcb[current].ss=_SS;
tcb[current].sp=_SP;
tcb[current].state=READY;
current=find();
_SS=tcb[current].ss;
_SP=tcb[current].sp;
tcb[current].state=RUNNING;
timecount=0;
enable();
线程阻塞过程:
将线程的状态改成阻塞态,将线程插入指定的阻塞队列末尾,并重新进行CPU调度。
线程唤醒过程:
把阻塞队列头上的第一个线程的TCB取下来,并将其状态改为就绪态,并重新进行CPU调度。
structblock_entry
{unsigned
thread;
structblock_entry*next;
};
structsemaphore
{
int
value;
structblock_entry*L;
voidInitSemaphore(structsemaphore*ps)
ps->
value=SIGNAL_VALUE;
L
=NULL;
voidblock(structsemaphore*ps)
structblock_entry*pbe;
tcb[current].state=BLOCKED;
pbe=(structblock_entry*)malloc(sizeof(structblock_entry));
pbe->
thread=current;
next
=ps->
L;
=pbe;
printf("
Thread%disblocked!
\n"
current);
voidwakeup(structsemaphore*ps)
pbe=ps->
if(!
pbe)
Blockqueueisempty!
);
tcb[pbe->
thread].state=READY;
L=pbe->
next;
free(pbe);
Thread%dhasbeenwakedup!
pbe->
thread);
voidwait(structsemaphore*ps)
value--;
if(ps->
value<
0)
block(ps);
voidsignal(structsemaphore*ps)
value++;
=0)
wakeup(ps);
假设刚开始时系统中有NBUF个消息缓冲区,它们排成一个消息队列freebuf,为实现对该队列操作的互斥,设置信号量mutexb(初值
为{1,NULL})。
发送消息时,发送者必须提供接收者的标识符、消息的长度及消息正文的起始地址等信息。
接收消息时,接收者必须指出发送者的标识符、接收区的起始地址等信息。
/*从空闲消息缓冲队列头上取下一缓冲区,返回指向该缓冲区的指针*/
structbuffer*getbuf()
structbuffer*buff;
buff=freebuf;
freebuf=freebuf->
returnbuff;
/*将buff所指向的消息缓冲区加到空闲消息缓冲队列中去*/
voiddropbuf(structbuffer*buff)
buff->
next=freebuf;
freebuf=buff;
/*将buff所指的缓冲区插到*mq所指的缓冲队列末尾*/
voidinsert(structbuffer**mq,structbuffer*buff)
structbuffer*temp;
if(buff==NULL)return;
next=NULL;
if(*mq==NULL)
*mq=buff;
else
temp=*mq;
while(temp->
next)
temp=temp->
temp->
next=buff;
/*从*mq所指的缓冲队列中移除buff所指的缓冲区*/
voiddelet(structbuffer**mq,structbuffer*buff)
*mq)return;
buff)return;
if(*mq==buff)
*mq=buff->
return;
for(temp=*mq;
temp->
next!
=buff;
temp=temp->
next);
next=buff->
/*将地址a开始的size个字节内容发送给receiver线程*/
voidsend(char*receiver,char*a,intsize)
inti,id=-1;
for(i=0;
strcmp(receiver,tcb[i].name))
id=i;
break;
if(-1==id)
Error:
Receivernotexsist!
wait(&
sfb);
mutexfb);
buff=getbuf();
signal(&
sender=current;
size=size;
size;
i++,a++)
text[i]=*a;
tcb[id].mutex);
insert(&
(tcb[id].mq),buff);
tcb[id].sm);
/*接收sender发送来的消息到a所指的缓冲区中*/
voidrecv(char*sender,char*a)
buff=tcb[current].mq;
while(buff)
/*printf("
%d\n"
buff->
sender);
*/
strcmp(sender,tcb[buff->
sender].name))
id=buff->
sender;
buff=buff->
if(-1==id)
Sendernotexsist!
i++,a++)
*a=buff->
text[i];
tcb[current].mutex);
delet(&
(tcb[current].mq),buff);
tcb[current].sm);
dropbuf(buff);
voidproduce()
for(i=0;
10;
i++){
disable();
production=rand()%(Y-X+1)+X;
production*=production;
fprintf(fp,"
current=%dprodece1produce_cnt=%dconsume_cnt=%dproduction=%d\n"
current,produce_cnt,consume_cnt,production);
enable();
wait(empty);
wait(mutex);
produce_cnt++;
current=%dprodece2produce_cnt=%dconsume_cnt=%dproduction=%d\n"
signal(mutex);
signal(full);
}
voidconsume()
current=%dconsume1produce_cnt=%dconsume_cnt=%dproduction=%d\n"
wait(full);
consume_cnt++;
current=%dconsume2produce_cnt=%dconsume_cnt=%dproduction=%d\n"
signal(empty);
六、实验结论
1、线程间通信的结果如下:
Thread1:
Sendthread2:
thread1tothread2-1!
Thread2:
Sendthread3:
thread2tothread3-1!
Thread3:
Sendthread1:
thread3tothread1-1!
thread1tothread2-2!
thread2tothread3-2!
thread3tothread1-2!
thread1tothread2-3!
thread2tothread3-3!
thread3tothread1-3!
thread1tothread2-4!
thread2tothread3-4!
thread3tothread1-4!
thread1tothread2-5!
thread2tothread3-5!
thread3tothread1-5!
Recvivemessage:
============Thread1isover!
============Thread2isover!
============Thread3isover!
2、生产者消费者问题的实现结果如下:
current=1prodece1produce_cnt=0consume_cnt=0production=2209
current=1prodece2produce_cnt=1consume_cnt=0production=2209
current=1prodece1produce_cnt=1consume_cnt=0production=961
current=1prodece2produce_cnt=2consume_cnt=0production=961
current=1prodece1produce_cnt=2consume_cnt=0production=1089
current=1prodece2produce_cnt=3consume_cnt=0production=1089
current=1prodece1produce_cnt=3consume_cnt=0production=1681
current=1prodece2produce_cnt=4consume_cnt=0production=1681
current=1prodece1produce_cnt=4consume_cnt=0production=49
current=1prodece2produce_cnt=5consume_cnt=0production=49
current=1prodece1produce_cnt=5consume_cnt=0production=324
Thread1isblocked!
current=2consume1produce_cnt=5consume_cnt=0production=324