基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx

上传人:b****2 文档编号:1048464 上传时间:2023-04-30 格式:DOCX 页数:23 大小:23.39KB
下载 相关 举报
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第1页
第1页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第2页
第2页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第3页
第3页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第4页
第4页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第5页
第5页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第6页
第6页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第7页
第7页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第8页
第8页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第9页
第9页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第10页
第10页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第11页
第11页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第12页
第12页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第13页
第13页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第14页
第14页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第15页
第15页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第16页
第16页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第17页
第17页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第18页
第18页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第19页
第19页 / 共23页
基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx_第20页
第20页 / 共23页
亲,该文档总共23页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx

《基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx(23页珍藏版)》请在冰点文库上搜索。

基于线程的多任务调度系统的设计及实现报告实验报告Word文档下载推荐.docx

send()函数:

消息的发送者需要提供接收者的标识符,消息的长度以及消息正文的起始地址等信息,然后在发送原语里申请一空闲的消息缓冲区,用相应的信息来装配该消息缓冲区,并把它插入到接收者的消息队列中去。

Receive()函数:

消息的接受者必须给出发送者的标识符,接受区的起始地址等信息,然后从自己的消息队列中取得相应的发送者发送来的消息缓冲区,将消息正文复制到接受区中,并释放相应的消息缓冲区。

源代码及解析如下

#include<

stdlib.h>

stdio.h>

dos.h>

#defineGET_INDOS0x34

#defineGET_CRIT_ERR0x5d06

/*定义四个状态*/

#definefinished0

#definerunning1

#defineready2

#defineblocked3

#defineTL3/*设置TL(时间片)时间为3*/

#defineNTCB10/*NTCB是系统允许的最多任务数也就是进程数*/

#defineNBUF5

#defineNTEXT30

/**********************声明变量********************/

charfar*indos_ptr=0;

charfar*crit_err_ptr=0;

intcurrent;

/*全部变量,始终等于正在执行的线程的内部标识符*/

inttimecount=0;

/*全局变量,等于上次调度至今的时间,在每次时钟中断发生时,timecount+1,通过它与TL课判断时间片是否到时,从而决定是否进行CPU调度*/

/********************定义数据结构********************/

typedefint(far*codeptr)(void);

/*定义codeptr函数指针*/

/*定义记录型信号量的数据结构*/

typedefstruct

{

intvalue;

structTCB*wq;

}semaphore;

semaphoremutexfb={1,NULL};

/*互斥信号量*/

semaphoresfb={NBUF,NULL};

/*空闲缓冲队列的计数信号量*/

/*消息缓冲区的数据结构*/

structbuffer

intsender;

/*消息发送者的标识数*/intsize;

/*消息长度<

=NTEXT个字节*/chartext[NTEXT];

structbuffer*next;

/指向下一个消息缓冲区的指针*/

};

structbuffer*freebuf;

/*空闲消息缓冲队列,是临界资源,由NBUF个空闲的消息缓冲区组成*/

/*定义TCB数据结构*/

structTCB{

unsignedchar*stack;

/*堆栈的起始地址*/

unsignedss;

/*堆栈的段址*/

unsignedsp;

/*堆栈的栈指针*

charstate;

/*线程的状态*/

charname[10];

/*线程的外部标示符*/

structTCB*next;

/*链接字段,把所有就绪的线程按某种方式排成一显式队列,如优先权从高到底的队列*/

structbuffer*mq;

/*消息队列队首指针*/

semaphoremutex;

/*消息队列的互斥信号量*/

semaphoresm;

/*消息队列计数信号量*/

}tcb[NTCB];

/*NTCB是系统允许的最多任务数*/

/*现场保护和恢复中要用到的一个数据结构*/

structint_regs{

unsignedbp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags,off,seg;

/**************************声明函数*************************/

intDosBusy(void);

voidInitInDos(void);

voidInitTcb(void);

/*对TCB的初始化*/

intcreate(char*name,codeptrcode,intstacklen);

voidover(void);

/*撤销线程,归还所占资源*/

voidinterrupt(*old_int8)(void);

/*原来的时间中断程序,需要先声明*/

voidinterruptnew_int8(void);

/*因时间片到时而引起的调度由new_int8()函数来完成*/

voidinterruptswtch(void);

/*其他原因引起的CPU调度由函数swtch()完成*/

voidtcb_state(void);

/*输出所有线程的状态信息*/

intall_finished(void);

voidp(semaphore*sem);

/*信号量P操作*/

voidv(semaphore*sem);

/*信号量V操作*/

/*********************函数的实现*********************/

/*******InitInDos函数的实现********/

voidInitInDos(void){

unionREGSregs;

structSREGSsegregs;

/*获得INDOSflag的地址*/

regs.h.ah=GET_INDOS;

intdosx(&

regs,&

segregs),

indos_ptr=MK_FP(segregs.es,regs.x.bx);

/*gettheaddressofCRIT_ERRflag*/

if(_osmajor<

3)

crit_err_ptr=indos_ptr+1;

elseif(_osmajor==3&

&

_osminor==0)

crit_err_ptr=indos_ptr-1;

else{

regs.x.ax=GET_CRIT_ERR,

intdosx(&

segregs);

crit_err_ptr=MK_FP(segregs.ds,regs.x.si);

}

}

/*************DosBusy函数的实现************/

intDosBusy(void){

if(indos_ptr&

crit_err_ptr)

return(*indos_ptr||*crit_err_ptr);

else

return(-1);

/************InitTcb函数的实现*************/

/*对TCB进行初始化*/

voidInitTcb(void){

inti;

for(i=1;

i<

NTCB;

i++){

tcb[i].stack=NULL;

tcb[i].state=finished;

strcpy(tcb[i].name,'

\0'

);

tcb[i].mq=NULL;

tcb[i].sm.value=0;

/*消息队列计数信号量*/

tcb[i].mutex.value=1;

/*缓冲区的互斥信号量*/

/*************create函数的实现****************/

/*创建一对应于函数name(外部标识符)的线程*/

intcreate(char*name,codeptrcode,intstacklen){

char*p;

structint_regs*pt;

/*第一步:

寻找空白的TCB*/

if(tcb[i].state==finished)

break;

/*第二步:

申请线程的私有堆栈内存空间,分配stacklen个字节长度的内存空间,利用malloc函数返回内存地址指针指向该内存空间,

所返回的值是该内存空间的起始地址*/

p=(char*)malloc(stacklen*sizeof(char));

/*获得堆栈的内存空间的高地址指针*/

p=p+stacklen

pt=(structint_regs*)p;

pt--;

pt->

flags=0x200;

/*flags寄存器的允许中断位*/

cs=FP_SEG(code);

/*代码段的段地址*/

ip=FP_OFF(code);

/*代码段的段内偏移地址*/

ds=_DS;

/*数据段的段地址*/

es=_ES;

/*附加数据段的段地址*/

off=FP_OFF(over);

/*撤销线程代码的偏移地址*/

seg=FP_SEG(over);

/*撤销线程代码的段址*/

/*第四步:

初始化线程的控制块TCB*/

strcpy(tcb[i].name,name);

/*填入线程的外部标识符*/

tcb[i].state=ready;

/*将线程的状态置成就绪态*/

tcb[i].stack=p-stacklen;

/*私有堆栈的起始地址*/

tcb[i].ss=FP_SEG(pt);

/*当前线程的段地址*/

tcb[i].sp=FP_OFF(pt);

/*当前线程的栈顶指针*/

returni;

/*返回线程的内部标示符*/

/************new_int8函数的实现***************/

/*系统调度,即时间中断到达后,判断时间片到后才运行,调用老的时钟中断*/

voidinterruptnew_int8(void){

(*old_int8)();

/*调用原来的时钟中断服务程序*/

timecount++;

/*每次发生中断时加1*/

if(timecount>

=TL){/*时间片到时*/

if(DosBusy())/*如果Dos忙*/

return;

disable();

/*关中*/

/*保护正在执行的线程current的现场,暂停它的执行*/

tcb[current].ss=_SS;

tcb[current].sp=_SP;

if(tcb[current].state==running)/*将执行状态变为就绪状态,暂停执行*/

tcb[current].state=ready;

/*找到以新的就绪线程*/

for(i=1;

if(tcb[i].state==ready&

i!

=current)/*找到除了当前线程的其他就绪线程*/

break;

}

/*如果没有找到就绪线程,那么就回复当前线程,继续执行*/

if(i>

=NTCB){

if(tcb[current].state==ready)

tcb[current].state=running;

enable();

/*如果超出了NTCB则恢复现场然后返回*/

/*如果找到就绪线程,那么恢复线程i的现场,把CPU分配给它*/

_SS=tcb[i].ss;

_SP=tcb[i].sp;

tcb[i].state=running;

/*置线程i为现有线程,并且重新开始计时*/

current=i;

timecount=0;

enable();

/*开中*/

return;

 

/*********swtch函数的实现************/

/*针对Swtch()函数的实现:

由于它是解决由其他因素所引起的CPU调度,在这个实现过程,只需要判断线程的执行状态即可,其他阻塞等状态不需要进行判断,或者可以直接对当前线程的现场进行保护,然后寻找就绪线程,分配CPU以及现场进行执行*/

/*Find()函数是为了寻找就绪线程而且是优先权大的线程(根据优先数越大,优先权越小的思想,在TCB设置以优先数,然后进行选择)*/

intFind()

inti,j;

for(i=0;

i++)

if(tcb[i].state==ready&

i!

=current)

break;

if(i==NTCB)

return-1;

for(j=i+1;

j<

j++)

{

if(tcb[j].state==ready&

j!

if(tcb[j].value>

tcb[i].value)

i=j;

/*swtch()调度,手工调度才能运行,处理因其他因素引起的中断*/

voidinterruptswtch(void)

i=Find();

if(i<

0)

i=0;

disable();

tcb[current].ss=_SS;

tcb[current].sp=_SP;

if(tcb[current].state==running)

tcb[current].state=ready;

_SS=tcb[i].ss;

_SP=tcb[i].sp;

tcb[i].state=running;

current=i;

enable();

/****************线程的阻塞和唤醒的实现****************/

/**(阻塞)block函数的实现**/

voidblock(structTCB**qp){

structTCB*tp;

tp=*qp;

tcb[current].state=blocked;

/*首先要将当前线程的状态置为阻塞状态*/

/*需要将线程插入到指定的阻塞队列未尾,并重新进行CPU调度*/

(*qp)->

next=NULL;

if(tp==NULL)

tp=&

tcb[current];

/*由于tp是一个指针,所以操作的是指针*/

while(tp->

next!

=NULL)

tp=tp->

next;

tp->

next=&

/*将阻塞线程插入到队尾*/

swtch();

/*并重新进行CPU调度*/

/**(唤醒)wakeup_first函数的实现**/

voidwakeup_first(structTCB**qp){

/*寻找阻塞线程,因为线程状态的改变需要在TCB中修改,所以需要知道阻塞队列里面需要唤醒的线程对应TCB数组里面的哪一个*/

if(strcmp(tcb[i].name,(*tp->

next).name)==0){/*如果两个外部标示符一样说明找到需要唤醒的线程*/

tcb[i].state=ready;

/*将其状态改为就绪状态*/

/***************线程的同步和互斥的实现****************/

/*用记录型信号量机制实现同步与互斥*/

/**对信号量的P操作**/

voidp(semaphore*sem){

structTCB**qp;

/*设置一个指向TCB链表的二级指针*/

/*关中断*/

sem->

value=sem->

value-1;

/*记录型信号量的value值减1*/

if(sem->

value<

0){/*如果记录型信号量的值小于0*/

qp=&

(sem->

wq);

/*那么将qp指针指向sem信号量的阻塞队列*/

block(qp);

/*阻塞相应进程到阻塞队列*/

/**对信号量的V操作**/

voidv(semaphore*sem){

qp=&

value+1;

=0){

wakeup_first(qp);

/***************消息缓冲队列的线程间的通信*************/

/**初始化消息队列**/

voidInitBuf(void){

structbuffer*freebuf,*temp;

freebuf=(structbuffer*)malloc(sizeof(structbuffer));

/*申请空间*/

temp=freebuf;

=NBUF;

temp=(structbuffer*)malloc(sizeof(structbuffer));

temp=temp->

/**从空闲消息缓冲队列头上取下一缓冲区,返回指向该缓冲区的指针**/

structbuffer*getbuf(void){

structbuffer*buff;

buff=freebuf;

/*空闲消息缓冲头*/

freebuf=freebuf->

returnbuff;

/**将buff所指的缓冲区插到*mq所指的缓冲队列尾**/

voidinsert(structbuffer**mq,structbuffer*buff){

structbuffer*temp;

if(buff==NULL)

return;

buff->

if(*mq==NULL)

*mq=buff;

temp=*mq;

while(temp->

temp=temp->

temp->

next=buff;

/***将地址a开始的size个字节发送给外部标示符为receiver的线程***/

voidsend(char*receiver,char*a,intsize){

inti,id=-1;

/*原语要关中断*/

/*首先需要进行搜索接受进程*/

if(strcmp(receiver,tcb[i].name)==0){

id=i;

break;

/*如果没有收到,那么就显示错误,没有接收进程*/

if(id==-1){

printf("

Error:

Receivernotexist!

\n"

return;

\n%ssend%samessage:

"

tcb[current].name,receiver);

%s\n"

a);

p(&

sfb);

/*sfb为空闲缓冲区队列的计数信号量,为全局变量*/

mutexfb);

/*mutexfb为互斥信号量*/

buf

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 文学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2