操作系统课程设计(一)时间片轮转实现多线程调度

 #include<stdlib.h>
#include<dos.h>
#include<stdio.h>

#define GET_INDOS 0x34 /* 34H 系统功能调用 */
#define GET_CRIT_ERR 0x5d06 /* 5D06H号系统功能调用 */

#define BLANK -1
#define FINISHED 0 /* 终止 */
#define RUNNING 1 /* 执行 */
#define READY 2 /* 就绪 */
#define BLOCKED 3 /* 阻塞 */
#define NTCB 10 /* 系统线程的最大数 */
#define TL 2 /* 时间片大小 */

char far* intdos_ptr=0;
char far* crit_err_ptr=0;

int timecount=0;
int current=-1;
int test;


struct TCB{ /* 线程控制块 */
 unsigned char* stack; /* 堆栈的起始地址 */
 unsigned ss;
 unsigned sp; /* 堆栈段址和堆栈指针 */
 char state; /* 进程状态 */
 char name[10]; /* 线程的外部标识符 */
}tcb[NTCB];

struct int_regs{ /* 现场保护和恢复结构体 */
 unsigned Bp,DI,SI,DS,ES,DX,CX,BX,AX,IP,CS,Flags,off,seg;
};

typedef int(far* codeptr)(void);

void interrupt(*old_int8)(void);

int DosBusy(void);
void InitIndos(void);
void InitTcb();
void interrupt new_int8(void);
void interrupt swtch();
void Create(char* name,codeptr code,int stacklen); /* 创建线程 */

void Destroy(int i);

void f1() /* 1#线程 */
{
 int i,j,k;
 
 for(i=0;i<40;i++)
 {
  printf("a");
  for(j=0;j<1000;j++)
   for(k=0;k<5000;k++);
 }
 
}

void f2() /* 2#线程 */
{
 int i,j,k;
 
 for(i=0;i<40;i++)
 {
  printf("b");
  for(j=0;j<1000;j++)
   for(k=0;k<5000;k++);
 }
 
 printf("/n");
}


void InitInDos() /* 取得INDOS标志和严重错误标志地址 */
{
 union REGS regs;
 struct SREGS segregs;
 
 regs.h.ah=GET_INDOS; /* 使用34H号系统功能调用 */
 intdosx(&regs,&regs,&segregs);
 
 intdos_ptr=MK_FP(segregs.es,regs.x.bx);
 
 if(_osmajor<3)
  crit_err_ptr=intdos_ptr+1; /* 严重错误在INDOS后一字节处 */
 else if(_osmajor==3&&_osminor==0)
  crit_err_ptr=intdos_ptr-1; /* 严重错误在INDOS前一字节处 */
 else
 {
  regs.x.ax=GET_CRIT_ERR;
  intdosx(&regs,&regs,&segregs);
  crit_err_ptr=MK_FP(segregs.ds,regs.x.si);
 }
}

int DosBusy(void) /* 判断DOS是否忙 */
{
 if(intdos_ptr&&crit_err_ptr)
  return(*intdos_ptr||*crit_err_ptr); /* DOS忙,返回严重错误标志 */
 else
  return(-1); /* DOS不忙 */
}

void InitTcb() /* 初始化线程 */
{
 int i;
 for(i=0;i<NTCB;i++)
 {
  tcb[i].state=BLANK; /* 初始状态标志 */
 }
}

void over()
{
 Destroy(current);
 swtch();
}

void Create(char *name,codeptr code,int stacklen)
{
 int i;
 struct int_regs *p;
 for(i=1;i<NTCB;i++)
 {
  if(tcb[i].state==BLANK||tcb[i].state==FINISHED)
   break;
 }
 if(i==NTCB)
  return;
 strcpy(tcb[i].name,name);
 tcb[i].stack=(unsigned char *)malloc(stacklen);
 tcb[i].stack+=stacklen;

 p=(struct int_regs *)tcb[i].stack;
 p--;
 p->Flags=0x200;
 p->CS=FP_SEG(code);
 p->IP=FP_OFF(code);
 p->off=FP_OFF(over);
 p->seg=FP_SEG(over);
 p->DS=_DS;
 p->ES=_ES;
 tcb[i].sp=FP_OFF(p);
 tcb[i].ss=FP_SEG(p);
 tcb[i].state=READY;
 return;
}

void Destroy(int i)
{
 disable();
 if(tcb[i].state==RUNNING)
 {
  disable();
  tcb[i].state=FINISHED;
  strcpy(tcb[i].name,NULL);
  free(tcb[i].stack);
  enable();
 }
 return;
}

void tcb_state() /* 线程状态信息 */
{
 int i;
 for(i=0;i<NTCB;i++)
  if(tcb[i].state!=BLANK)
  {
   switch(tcb[i].state)
   {
   case FINISHED:
    printf("tcb[%d] is FINISHED/n",i);
    break;
   case RUNNING:
    printf("tcb[%d] is RUNNING/n",i);
    break;
   case READY:
    printf("tcb[%d] is READY/n",i);
    break;
   case BLOCKED:
    printf("tcb[%d] is BLOCKED/n",i);
    break;
   }
  }
}

int Find()
{
 int i;
 for(i=current +1 ;i<NTCB;i++)
  if(tcb[i].state==READY)
  {
   return i;
  }
  for(i = 0; i < current; i++)
   if(tcb[i].state==READY)
   {
    return i;
   }
   if(i==NTCB)
    return -1;
}

void interrupt new_int8(void) /* CPU 调度*/
{
 int i;
 (*old_int8)();
 timecount++;
 
 if(timecount >= TL)
 {
  if(DosBusy())
  {
   return;
  }
  else
  {
   int  ready;
   disable();
   
   /*保存旧线程的指针*/
   tcb[current].ss = _SS;
   tcb[current].sp = _SP;
   if(tcb[current].state == RUNNING)
    tcb[current].state = READY;
   ready = Find();
   /*切换线程*/
   _SS = tcb[ready].ss;
   _SP = tcb[ready].sp;
   tcb[ready].state = RUNNING;
   current=ready;
   timecount=0;
   enable();
  }
 }
}

void interrupt swtch() /* 其他原因CPU调度 */
{
 int i; 
 i=Find();
 if(i<0)
  return;
 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();
}

int all_finished()
{
 int i;
 for(i=1;i<NTCB;i++)
  if(tcb[i].state==RUNNING||tcb[i].state==BLOCKED||tcb[i].state==READY)
   return 0;
  return 1;
}

void main()
{
 
 InitInDos();
 InitTcb();
 
    old_int8=getvect(8);
 strcpy(tcb[0].name,"main");
 tcb[0].state=RUNNING;
 current=0;

 Create("f1",(codeptr)f1,1024);
 Create("f2",(codeptr)f2,1024);  
 tcb_state();

 setvect(8,new_int8);
 swtch();

 while(!all_finished());
 tcb[0].name[0]='/0';
 tcb[0].state=FINISHED;
 setvect(8,old_int8);

 tcb_state();
 printf("/nMuli_task system teminated /n");
 system("PAUSE");
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[提示] (1)假定系统有五个进程,每一个进程用一个进程控制块PCB来代表。进程控制块的格式为: 进程名 指针 要求运行时间 已运行时间 状态 其中,进程名----作为进程的标识,假设五个进程的进程名分别是Q1,Q2,Q3,Q4,Q5。 指针----进程按顺序排成循环队列,用指针指出下一个进程的进程控制块首地址,最后一个进程中的指针指出第一个进程的进程控制块首地址。 要求运行时间----假设进程需要运行的单位时间数。 已运行时间----假设进程已经运行的单位时间数,初始值为“0”。 状态----有两种状态,“就绪”状态和“结束”状态,初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态变为“结束”,用“E”表示。 (2)每次运行你所设计的处理器调度程序之前,为每个进程任意确定它的“要求运行时间”。 把五个进程按顺序排成循环队列,用指针指出队列连接情况。另用一标志单元记录轮到运行的进程。 (3)处理器调度总是选择标志单元指示的进程运行。由于本实验是模拟处理器调度的功能,所以,对被选中的进程并不实际启动运行,而是执行: 已运行时间-1 来模拟进程的一次运行,表示进程已经运行过一个单位的时间。 请注意:在实际的系统中,当一个进程被选中运行时,必须置上该进程可以运行的时间片值,以及恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行满一个时间片。在这里省去了这些工作,仅用“已运行时间+1”来表示进程已经运行满一个时间片。 (4)进程运行一次后,应把该进程的进程控制块中的指针值送到标志单元,以指示下一个轮到运行的进程。同时,应判断该进程的要求运行时间与已运行时间,若该进程要求运行时间≠已运行时间,则表示它尚未执行结束,应待到下一轮时再运行。若该进程的要求运行时间=已运行时间,则表示它已经执行结束,应把它的状态修改为“结束”(E)且退出队列。此时,应把该进程的进程控制块中的指针值送到前面一个进程的指针位置。 (5)若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。 (6)在所设计的称序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进称对列的变化。 (7)为五个进程任意确定一组“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值