⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 11.c

📁 线程的调度模拟ok
💻 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(&regs,&regs,&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(&regs,&regs,&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 + -