操作系统课程设计之线程.docx
- 文档编号:29989073
- 上传时间:2023-08-04
- 格式:DOCX
- 页数:26
- 大小:23.59KB
操作系统课程设计之线程.docx
《操作系统课程设计之线程.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计之线程.docx(26页珍藏版)》请在冰豆网上搜索。
操作系统课程设计之线程
/*说明:
本程序中,默认以tcb下标为就绪队列,即从tcb[0]~tcb[NTCB-1]为轮转执行,程序中出现的id均为线程内部标识,即tcb的下标*/
#include
#include
#include
#include
#defineGET_INDOS0X34/*参见实验指导书*/
#defineGET_CRIT_ERR0X5D06/*参见实验指导书*/
#defineNTCB5/*NTCB是系统允许的最多线程数,也就是允许的线程控制块最大数*/
#defineNBUF5/*空闲缓冲区的数量*/
#defineNTEXT20/*在线程间传送信息时,信息的上限*/
#defineFINISHED0/*表示线程处于终止态或TCB是空闲状态*/
#defineRUNNING1/*表示线程处于运行态*/
#defineREADY2/*表示线程处于就绪态*/
#defineBLOCKED3/*表示线程处于阻塞态*/
intcurrent=0;/*当前TCB,初始=0*/
inttimecount=0;/*时间计数*/
intTL=1;/*时间片大小*/
charfar*indos_ptr=0;/*该指针变量存放INDOS标志的地址*/
charfar*crit_err_ptr=0;/*该指针变量存放严重错误标志的地址*/
/*记录型信号量的定义,参见课本51页*/
typedefstruct{
intvalue;/*资源数目*/
structTCB*wq;/*线程链表指针,链接所有等待线程*/
}semaphore;
structTCB{
unsignedchar*stack;/*线程堆栈的起始地址*/
unsignedss;/*堆栈段址*/
unsignedsp;/*堆栈指针*/
charstate;/*线程状态:
执行、就绪、阻塞*/
charname[10];/*线程的外部标识符*/
structbuffer*mq;/*消息队列队首指针*/
semaphoremutex;/*消息队列互斥信号量*/
semaphoresm;/*消息队列资源信号量,用于实现同步*/
structTCB*next;/*阻塞时TCB排队*/
}tcb[NTCB];
/*buf[NBUF]消息缓冲区的定义,freebuf空闲缓冲队列,临界资源(需互斥访问,设置mutexfb信号量)。
参见课本70页*/
structbuffer{
intsender;/*消息发送者的内部标识*/
intsize;/*消息长度*/
chartext[NTEXT];/*消息正文*/
structbuffer*next;/*指向下一个消息缓冲区的指针*/
}buf[NBUF],*freebuf;
semaphoremutexfb={1,NULL};/*对空闲消息缓冲队列处理的互斥信号量*/
semaphoresfb={NBUF,NULL};/*计数用的资源信号量*/
typedefint(far*codeptr)(void);/*函数指针,指向一个函数的起始地址*/
voidinterrupt(*old_int8)(void);/*旧中断程序的函数指针*/
/*以下为函数的声明*/
voidInitDos(void);
intDosBusy(void);
voidInitTcb(void);
voidInitBuff(void);
intcreate(char*name,codeptrcode,intstacklen);/*Create()线程创建初始化*/
voidinterruptnew_int8(void);
voidinterruptswtch(void);/*swtch()线程调度*/
voiddestroy(intid);/*destroy()线程撤销函数*/
voidover(void);/*over()撤销线程并重新进行调度*/
voidFind_TRRS(void);/*Round-RobinScheduling轮转调度*/
voidsender(void);
voidreceiver(void);
voidtcb_state(void);/*输出所有线程的状态信息*/
intfinished();/*检查系统中除0#线程外的其他线程是否执行完,是返回1,否返回0*/
intreceive(char*sender,char*b);
voidsend(char*receiver,char*a,intsize);
voidinsert(structbuffer**mq,structbuffer*buff);
structbuffer*getbuf(void);
voidv(semaphore*sem);
voidp(semaphore*sem);
voidwakeup(structTCB**qp);
voidblock(structTCB**qp);
/*以上为函数的声明*/
/**********************************************************
*函数:
voidmain(void)
*功能:
主函数
**********************************************************/
voidmain(void)
{
InitDos();/*获得INDOS标志的地址和严重错误标志的地址*/
InitTcb();/*初始化线程控制块*/
InitBuff();/*初始化缓冲区*/
old_int8=getvect(8);/*取得8号中断向量入口*/
/*初始化0号线程的TCB,current为正在执行线程的内部标识*/
strcpy(tcb[0].name,"main");
tcb[0].state=RUNNING;
current=0;
/*创建sender、receiver线程*/
create("sender",(codeptr)sender,1024);
create("receiver",(codeptr)receiver,1024);
tcb_state();/*打印所有线程状态*/
/*设置新的中断程序并进行线程调度*/
setvect(8,new_int8);
swtch();
/*如果除0号线程外的其他线程没有执行结束,就进行调度*/
while(!
finished())
swtch();
/*修改tcb[0]的值,结束0号线程,终止多任务系统*/
tcb[0].name[0]='\0';
tcb[0].state=FINISHED;
setvect(8,old_int8);/*运行结束后,设置8号中断程序为dos原始的中断程序*/
tcb_state();/*输出线程状态*/
printf("\n-----Multi_tasksystemterminated.-----\n");
system("pause");
}
/**********************************************************
*函数:
voidInitDos(void)
*功能:
获得INDOS标志的地址和严重错误标志的地址,详细注释请参考实验指导书17,18页
**********************************************************/
voidInitDos(void){
unionREGSregs;
structSREGSsegregs;
regs.h.ah=GET_INDOS;
intdosx(®s,®s,&segregs);
indos_ptr=MK_FP(segregs.es,regs.x.bx);
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(®s,®s,&segregs);
crit_err_ptr=MK_FP(segregs.ds,regs.x.si);
}
}
/**********************************************************
*函数:
intDosBusy(void)
*功能:
获得indos标志及严重错误标志的值,判断是否dos忙,详细注释请参考实验指导书17,18页
**********************************************************/
intDosBusy(void){
if(indos_ptr&&crit_err_ptr)
return(*indos_ptr||*crit_err_ptr);
else
return(-1);
}
/**********************************************************
*函数:
voidInitTcb(void)
*功能:
初始化TCB,给所有tcb线程控制块赋初值。
**********************************************************/
voidInitTcb(void){
intid;
for(id=0;id tcb[id].stack=NULL; tcb[id].state=FINISHED; tcb[id].name[0]='\0'; tcb[id].mq=NULL; tcb[id].mutex.value=1; tcb[id].mutex.wq=NULL; tcb[id].sm.value=0; tcb[id].sm.wq=NULL; tcb[id].next=NULL; } } /********************************************************** *函数: voidInitBuff(void) *功能: 初始化空闲消息缓冲队列,并链接成一个队列,在需要用到缓冲区时,从freebuf空闲缓冲队列中获取 **********************************************************/ voidInitBuff(void){ inti; for(i=0;i buf[i].next=&buf[i+1];/*从第一个开始的缓冲区指针均指向下一个缓冲区(除最后一个为空外)以链接成队列*/ buf[i].next=NULL; freebuf=&buf[0];/*将所有空闲缓冲区插入到缓冲队列中*/ } /********************************************************** *函数: intcreate(char*name,codeptrcode,intstck) *功能: 线程的创建,指导书第6,7页及ppt。 请记住SS,SP,DS,CS,IP,FLAG等寄存器的名称及作用,CS和IP的作用相当于组成原理里的PC程序计数器。 **********************************************************/ intcreate(char*name,codeptrcode,intstck){ structint_regs{/*为方便线程私有堆栈的初始化工作,设置该结构体*/ unsignedbp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags,off,seg; }*xp;/*xp为结构体指针*/ inti; intid=-1; char*p; /*查找空闲的TCB,如果有则分配tcb*/ for(i=0;i if(tcb[i].state==FINISHED){ id=i; break; } } if(id==-1) return(0); /*关中断*/ disable(); p=malloc(stck);/*私有栈空间分配*/ tcb[id].stack=p;/*tcb[id].stack指向栈的最顶端,线程结束时,释放栈空间时使用*/ p=p+stck;/*p指针指向栈底*/ xp=(structint_regs*)p;/*xp指向栈底*/ xp--; xp->seg=FP_SEG(over);/*over函数的入口地址存到堆栈的底部,在线程执行完后,会自动调用over函数结束自己*/ xp->off=FP_OFF(over); xp->flags=0x200;/*标志寄存器,置第9位IF标志为1,即允许可屏蔽中断*/ xp->cs=FP_SEG(code);/*线程所指向的函数的入口地址,在调度时,恢复现场信息时,CS和IP会指向函数入口,即开始执行某线程*/ xp->ip=FP_OFF(code); xp->es=_ES;/*ES附加段寄存器,这里也可以用_DS*/ xp->ds=_DS;/*DS数据段寄存器*/ tcb[id].ss=FP_SEG(xp);/*将堆栈段基址保存在线程tcb的ss里,保存的是线程私有栈的基地址*/ tcb[id].sp=FP_OFF(xp);/*将堆栈的偏移地址保存在tcb的sp里,保存的是线程私有栈的偏移地址*/ tcb[id].state=READY;/*创建完线程后,将线程插入到就绪队列中,因为本程序中默认tcb下标为就绪队列,所以只需修改线程状态为READY即可*/ strcpy(tcb[id].name,name); printf("\n-----Tread(%s)issuccessfullycreated.-----\n",tcb[id].name); enable();/*开中断*/ return (1); } /********************************************************** *函数: voidFind_TRRS() *功能: 时间片轮转调度算法,从tcb[0]到tcb[NTCB-1]轮转执行 * **********************************************************/ voidFind_TRRS(void){ inti=0,id; if(++current==NTCB)/*从当前执行线程的下一个就绪线程开始,如果当前线程是tcb[NTCB-1],则转回tcb[0],相当于数据结构中的循环队列*/ current=0; for(;tcb[current].state! =READY&&i current++; if(current==NTCB)current=0; } if(tcb[current].state! =READY)current=0;/*查找不到就绪的线程时,就回到0号线程执行*/ } /************************************************ *函数: voidinterruptswtch() *功能: 线程调度 ************************************************/ voidinterruptswtch(){ /*关中断*/ disable(); /*保护正在执行的线程current的现场并暂停它的执行*/ tcb[current].ss=_SS; tcb[current].sp=_SP; if(tcb[current].state==RUNNING) tcb[current].state=READY; /*找到一个新的就绪线程*/ Find_TRRS(); /*恢复找到的线程的现场,把CPU分派给它*/ _SS=tcb[current].ss; _SP=tcb[current].sp; tcb[current].state=RUNNING; /*重新开始计时(时间片轮转)*/ timecount=0; /*开中断,此后出现的开关中断不再加注释*/ enable(); } /************************************************ *函数: voiddestroy(intid) *功能: 销毁 ************************************************/ voiddestroy(intid){ disable(); free(tcb[id].stack);/*释放私有堆栈空间*/ tcb[id].stack=NULL; tcb[id].state=FINISHED;/*修改线程状态为终止*/ printf("\n----Thread%sisterminated----\n",tcb[id].name); tcb[id].name[0]='\0';/*修改tcb名称为空,释放tcb*/ enable(); } /********************************************************** *函数: voidover(void) *功能: 调用destroy()函数销毁线程并重新调度 **********************************************************/ voidover(void) { destroy(current); swtch(); } /********************************************************** *函数: voidtcb_state(void) *功能: 输出tcb状态 **********************************************************/ voidtcb_state(void){ intid; putchar('\n'); for(id=0;id printf("Thread%d(%s): ",id,tcb[id].name); switch(tcb[id].state){ caseREADY: printf("READY\n");break; caseRUNNING: printf("RUNNING\n");break; caseFINISHED: printf("FINISHED\n");break; caseBLOCKED: printf("BLOCKED\n");break; } } putchar('\n'); } /********************************************************** *函数: voidinterruptnew_int8(void) *功能: 新的中断程序 **********************************************************/ voidinterruptnew_int8(void){ (*old_int8)(); timecount++;/*时间片轮转计时*/ /*如果时间片到了或者dos忙,直接返回原线程执行不进行调度,若时间片到了且dos不忙则进行调度*/ if(timecount return; if(DosBusy())/*判断dos是否忙*/ return; swtch(); } /********************************************************** *函数: intfinished() *功能: 判断除0#外的其他线程是否全部结束,是返回1,否则返回0 **********************************************************/ intfinished(){ inti; for(i=1;i i
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 课程设计 线程