📄 11.c
字号:
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#define finished 0 /*结束*/
#define running 1 /*运行*/
#define ready 2 /*就绪*/
#define blocked 3 /*阻塞*/
#define NTCB 10 /*系统最多线程数,其中0号为系统0#线程对应main函数*/
#define TL 3 /*时间片*/
#define NTEXT 10
#define GET_INDOS 0x34 /*取得INDOS标志*/
#define GET_CRIT_ERR 0x5d06 /*取得严重错吴标志*/
char far *indos_ptr=0;
char far *crit_err_ptr=0;
void interrupt(*old_int8)(void); /*原来INT 08的入口地址,并保存*/
int timecount=0; /*时间片轮转调度记数*/
int current=0; /*永远指向当前线程*/
struct tcb /*线程控制块TCB*/
{
unsigned char *stack; /*私栈的始址*/
unsigned ss; /*私栈的段指针*/
unsigned sp; /*私栈的偏移量*/
int state; /*线程的状态*/
char name[10]; /*线程名*/
int flag; /*线程标志,为1时已分配*/
}tcb[NTCB];
typedef struct int_regs /*现场信息*/
{
unsigned bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags,off,seg;
}*reg;
/*InitInDos
*Function to get the addresses of INDOS and CRIT_ERR flags
*/
void InitInDos(void)
{
union REGS regs;
struct SREGS segregs;
/*get the addresses of INDOS flag*/
regs.h.ah=GET_INDOS;
intdosx(®s,®s,&segregs);
indos_ptr=MK_FP(segregs.es,regs.x.bx);
/*get the addresses of CRIT_ERR flag*/
if(_osmajor<3)
crit_err_ptr=indos_ptr+1;
else if(_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);
}
return;
}
/*DosBusy
*Function return non_zero if DOS is busy
*/
int DosBusy(void)
{
if(indos_ptr&&crit_err_ptr)
return(*indos_ptr&&*crit_err_ptr);
else
return(-1);/*InitInDos()hasn't been called*/
}
void InitTCB(void) /*系统初始*/
{
int i;
for(i=0; i<NTCB; i++)
tcb[i].flag=0; /*设置为空白tcb*/
return;
}
void over(void);
typedef int (far *codeptr)(); /*定义codeptr是指向函数的指针*/
int create(char *name,codeptr f,int stacklen) /*创建线程*/
{ /*void over();*/
int i;
reg regstack;
for(i=0;i<NTCB;i++)
if(tcb[i].flag==0)
break; /*寻找空闲tcb*/
if(i==NTCB)
{
printf("there is no blank tcb!\n");
return 1; /*未找到空闲tcb,默认失败时返回1*/
}
tcb[i].stack=(char *)malloc(stacklen); /*申请私有堆栈空间*/
regstack=(reg)(tcb[i].stack+stacklen); /*指向私栈栈顶*/
regstack--;
regstack->flags=0x200; /*flags寄存器置允许中断*/
regstack->cs=FP_SEG((codeptr)f); /*线程对应函数的段址*/
regstack->ip=FP_OFF((codeptr)f); /*线程对应函数的偏移量*/
regstack->seg=FP_SEG((codeptr)over); /*撤消函数的段址*/
regstack->off=FP_OFF((codeptr)over); /*撤消函数的偏移量*/
regstack->ds=_DS; /*数据段*/
regstack->es=_ES; /*附加段*/
tcb[i].ss=FP_SEG(tcb[i].stack); /*初始化tcb私有堆栈指针*/
tcb[i].sp=(unsigned)regstack;
strcpy(tcb[i].name,name);
tcb[i].flag=1;
tcb[i].state=ready;
return i;
}
void tcb_state(void) /*查看线程状态*/
{
int i;
for(i=0;i<NTCB;i++)
if(tcb[i].flag==1)
{
printf("%s is ",tcb[i].name);
switch (tcb[i].state)
{
case 0: {printf("%s","finished");break;}
case 1: {printf("%s","running"); break;}
case 2: {printf("%s","ready"); break;}
case 3: printf("%s","blocked");
}
printf("\n");
}
return;
}
void interrupt swtch() /*因为线程执行完毕或当前线程等待事件而进行的线程调度,系统自动保存现场*/
{
int i;
disable();
tcb[current].sp=_SP; /*保存当前的堆栈的地址指针*/
tcb[current].ss=_SS;
for(i=1;i<10;i++)
{ /*寻找就绪的线程,并进行切换*/
if(tcb[i].flag==1&&tcb[i].state==ready)
{
tcb[current].state=ready;
current=i;
tcb[current].state=running;
break;
}
}
if(i==10) /*无可切换的就绪线程,则把控制权交给系统0#线程*/
{ current=0;tcb[current].state=running; }
_SP=tcb[current].sp; /*切换当前线程的堆栈指针*/
_SS=tcb[current].ss;
timecount=0; /*此句用于按时间片轮转调度时的重新记时,在其他调度中多余*/
enable();
return;
}
void interrupt new_int8 (void) /*按时间片进行调度的新的时钟中断处理程序*/
{
(*old_int8)();
timecount++;
printf("here is an interrupt!\n");
if(timecount>=TL&&DosBusy()==0)
swtch(); /*时间片到并且系统不忙,调用swtch,完成剩余的切换工作*/
return;
}
void over(void) /*撤消当前线程,调度就绪线程*/
{
disable(); /*关中断*/
tcb[current].flag=0; /*撤消当前线程*/
free(tcb[current].stack); /*释放私有堆栈空间*/
tcb[current].state=finished;
swtch(); /*调度就绪线程*/
enable(); /*开中断*/
return;
}
int all_finished(void) /*检查除了0#线程以外的线程是否全部完成*/
{
int i;
for(i=1; i<NTCB; i++)
if(tcb[i].flag==1&&tcb[i].state!=finished)
return 0;
return 1;
}
void f1(void)
{
int i,j,k;
for(i=0; i<40; i++)
putchar('a');
for(j=0; j<10000; j++)
for(k=0; k<10000; k++);
printf("f1 have called!\n");
return;
}
void f2(void)
{
int i,j,k;
for(i=0; i<40; i++)
putchar('b');
for(j=0; j<1000; j++)
for(k=0; k<10000; k++);
printf("f2 have called!\n");
return;
}
void f3(void)
{
int i,j,k;
for(i=0; i<40; i++)
putchar('c');
for(j=0; j<15000; j++)
for(k=0; k<1000; k++);
printf("f3 have called!\n");
return;
}
void main()
{
InitInDos(); /*初始化系统*/
InitTCB(); /*初始化线程*/
old_int8=getvect(8); /*获取原来的 INT 08 的入口地址并保存*/
strcpy(tcb[0].name,"main");/*系统0线程*/
tcb[0].flag=1;
tcb[0].state=running;
tcb[0].stack=(char *)malloc(1024);
create("f1",(codeptr)f1,1024);
create("f2",(codeptr)f2,1024);
create("f3",(codeptr)f3,1024);
tcb_state();
setvect(8,new_int8);
swtch();
while(!all_finished());
tcb[0].name[0]='\0';
tcb[0].state=finished;
free(tcb[current].stack);
setvect(8,old_int8);
tcb_state();
printf("\nMulti_task systerm terminated.\n");
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -