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

📄 ossystem.c

📁 基于DOS的多任务系统的实现 1. 用C语言完成线程的创建和撤消
💻 C
字号:
#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 1           /* 时间片大小  */
#define NBUF 10        /* 消息缓冲区数目 */
#define NTEXT 50             /* 文本输出大小  */

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

int timecount=0;
int current=-1;

typedef struct{            /* 信号量 */
  int value;
  struct TCB* wq;
}semaphore;

semaphore mutexfb={1,NULL};
semaphore sfb={10,NULL};

semaphore test={0,NULL};
semaphore test2={0,NULL};

struct buffer{       /* 消息缓冲区    */
  int sender;        /* 消息发送者的标识数    */
  int size;         /* 消息长度<=NTEXT 个字节    */
  char text[NTEXT];           /* 消息正文    */
  struct buffer* next;      /* 指向下一个消息缓冲区的指针 */
}*freebuf;

struct TCB{           /* 线程控制块  */
  unsigned char* stack;          /* 堆栈的起始地址  */
  unsigned ss;
  unsigned sp;            /* 堆栈段址和堆栈指针 */
  char state;             /* 进程状态   */
  char name[10];          /* 线程的外部标识符  */
  int value;
  struct TCB* next;       /* 指向控制快指针  */
  struct buffer* mq;      /* 消息缓冲队列首指针  */
  semaphore mutex;        /* 互斥信号量   */
  semaphore sm;           /* 消息缓冲队列计数信号量*/
}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 send(char *receiver,char *a,int size);
void receive(char *sender,char *a);
void p(semaphore *sem);
void v(semaphore *sem);

int Create(char* name,codeptr code,int stacklen,int value);  /* 创建线程 */

/*void interrupt(&old_int8)(void)

{
 old_int8=getvect(8);
}*/

void Destroy(int i);

void f1()        /* 1#线程  */
{
  long i,j,k;
/*test the message*/
  send("f2","f1 send message to f2",NTEXT);
  v(&test2);
  p(&test);
/*test the call*/
/* for(i=0;i<20;i++)
    {
     putchar(`a`)
     for(j=0;j<1000;j++)
      for(k=0;k<20000;k++);
    }*/
/*test the mutex*/
/*for(i=0;i<=30;i++)
   {
     putchar(`a`);
     if(i%5==0);
     p(&mutexfb);
     v(&test);
   }*/
}

void f2()           /* 2#线程  */
{
  long i,j,k;
/*test the message*/
/*char*a=(char*)malloc((20*sizeof(char);*/
  char a[NTEXT];
  p(&test2);
  receive("f1",a);
  v(&test);
  printf("%s",a);

/*test the call*/
/*for(i=0;i<10;i++)
  {
    putchar(`b`);
    for(j=0;j<1000;j++)
    for(k=0;k<20000;k++);
   }*/

/*test the mutex*/
/*for(i=o;i<=30;i++)
  {
    putchar(`b`);
    if(i%5==0)
     v(&mutexfb);
    v(&test);
}*/
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;       /* 初始状态标志   */
    tcb[i].mq=NULL;
    tcb[i].mutex.value=1;
    tcb[i].mutex.wq=NULL;
    tcb[i].sm.value=0;
    tcb[i].sm.wq=NULL;
   }
}

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

int Create(char*name,codeptr code,int stacklen,int value)
{
   int i;
   char*p;
   struct int_regs*pt;
   for(i=1;i<NTCB;i++)
   {
     if(tcb[i].state==BLANK||tcb[i].state==FINISHED)
         break;
   }
   if(i==NTCB)
     return-1;
   tcb[i].value=value;
   strcpy(tcb[i].name,name);
   tcb[i].stack=p=(unsigned char*)malloc(stacklen);
   p=p+stacklen;
   pt=(struct int_regs*)p;
   pt--;
   pt->Flags=0x200;
   pt->CS=FP_SEG(code);
   pt->IP=FP_OFF(code);
   pt->off=FP_OFF(over);
   pt->seg=FP_SEG(over);
   pt->DS=_DS;
   pt->ES=_ES;
   tcb[i].sp=FP_OFF(pt);
   tcb[i].ss=FP_SEG(pt);
   tcb[i].state=READY;
   return i;
}

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,j;
   for(i=0;i<NTCB;i++)
   if(tcb[i].state==READY&&i!=current)
    break;
 for(j=i+1;j<NTCB;j++)
 {
   if(tcb[j].state==READY&&j!=current)
     if(tcb[j].value>tcb[i].value)
   i=j;
 }
 if(i==NTCB)
   return -1;
 return i;
}

void interrupt new_int8(void)       /* CPU 调度*/
{
  int i;
  (*old_int8)();      /* 指向原来时钟中断处理过程入口的中断处理函数指针 */
  timecount++;
  if(timecount==TL)        /* 时间片是否到? */
  {
    if(!DosBusy())     /* DOS是否忙? */
   {
  disable();
  tcb[current].ss=_SS;     /* 保存现场 */
  tcb[current].sp=_SP;
  if(tcb[current].state==RUNNING)
      tcb[current].state=READY;
  i=Find();
  if(i<0)
   return;
  _SS=tcb[i].ss;
  _SP=tcb[i].sp;
  tcb[i].state=RUNNING;
  current=i;
  timecount=0;      /* 重新计时 */
  enable();
   }
   else
     return;
  }
   else
     return;
}

void interrupt swtch()            /* 其他原因CPU调度  */
{
  int i;
  if(tcb[current].state!=FINISHED&&current!=0&&tcb[current].state!=BLOCKED) /* 当前线程还没结束 */
     return;
  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 block(struct TCB**p)         /* 阻塞原语 */
{
  struct TCB*pl;
  tcb[current].state=BLOCKED;

  if((*p)==NULL)
     *p=&tcb[current];    /* 阻塞队列空,直接放入 */
  else
  {
   pl=*p;
   while(pl->next!=NULL)
   pl=pl->next;         /* 找到阻塞队列最后一个节点 */
   pl->next=&tcb[current];      /* 放入阻塞队列 */
  }
   tcb[current].next=NULL;
   swtch();       /* 重新进行CPU调度 */
}

void wakeup_first(struct TCB**p)    /* 唤醒队首线程 */
{
  struct TCB*pl;
  if((*p)==NULL)
      return;
  pl=(*p);
  (*p)=(*p)->next;     /* 得到阻塞队列队首线程 */
  pl->state=READY;        /* 修为就绪状态 */
  pl->next=NULL;
}

void p(semaphore*sem)
{
  struct TCB**qp;
 
  disable();
   sem->value=sem->value-1;
   if(sem->value<0)
    {
     qp=&(sem->wq);
     block(qp);
    }
   enable();
}

void v(semaphore*sem)
{
  struct TCB**qp;
  disable();
   qp=&(sem->wq);
   sem->value=sem->value+1;
   if(sem->value>=0)
      wakeup_first(qp);
   enable();
}

struct buffer*Initbuf(void) 
{
  
  struct buffer *p,*pt,*pt2;
  int i;
  pt2=pt=(struct buffer*)malloc(sizeof(struct buffer));
  pt->sender=-1;
  pt->size=0;
  strcmp(pt->text,"");
  pt->next=NULL;
  for(i=0;i<NBUF-1;i++)
  {
   p=(struct buffer*)malloc(sizeof(struct buffer));
   p->sender=-1;
   p->size=0;
   p->text[NTEXT]='\0';
   p->next=NULL;
   pt2->next=p;
   pt2=p;
  }
  return pt;
}

struct buffer*getbuf(void)  /* 从空闲消息缓冲队列队头上取下一缓冲区 */

{
  struct buffer*buff;
  buff=freebuf;        /* 取得缓冲队列的缓冲区*/
  freebuf=freebuf->next;
  return(buff);        /* 返回指向该缓冲区的指针 */
}

void putbuf(struct buffer*pt)
{
  struct buffer*p=freebuf;
  while(p->next!=NULL)
    p=p->next;
  p->next=pt;
  pt->next=NULL;
}

void insert(struct buffer**mq,struct buffer*buff)
{     /* 将buff所指的缓冲区插到*mq所指的缓冲队列末尾*/
  struct buffer*temp;
  
  if(buff==NULL)return;       /* buff为空 */
  buff->next=NULL;
  if(*mq==NULL)     /* *mq为空 则直接插入*/
    *mq=buff;
  else
  {
   temp=*mq;
   while(temp->next!=NULL)      /* 找到队尾 */
    temp=temp->next;
   temp->next=buff;      /* 插入队列末尾 */
  }
}

void send(char*receiver,char*a,int size)
{   /* 将地址a开始的size个字节发送给外部标识符为receiver的线程 */
  struct buffer*buff;
  int i,id=-1;
  disable();
  for(i=0;i<NTCB;i++)      /* 找receiver相对应的线程号*/
  {
    if(strcmp(receiver,tcb[i].name)==0)
      {
        id=i;
        break;
      }
  }
  if(id==-1)         /* 没找到 */
    {
     printf("Error:Receiver not exist!\n");
     enable();
     return;
    }
p(&sfb);     /* 空闲缓冲队列数量的互斥操作   */
  p(&mutexfb);     /* 空闲缓冲队列资源的互斥操作   */
  buff=getbuf();    /* 获得一缓冲区 */
  v(&mutexfb);
  buff->sender=current;
  buff->size=size;
  buff->next=NULL;
  for(i=0;i<buff->size;i++,a++)   /* 写入缓冲队列   */
   buff->text[i]=*a;
  p(&tcb[id].mutex);     /* 相应线程的消息缓冲队列互斥操作   */
   insert(&(tcb[id].mq),buff);/* buff所指的缓冲区插到相应线程的消息缓冲队列末尾 */
   v(&tcb[id].mutex);
   v(&tcb[id].sm);    /* 对应于p(&sfb),线程的消息缓冲队列数量的互斥操作   */
  
  enable();
}

void receive(char *sender,char *a)
{
  struct buffer *buff;
  int i;
  disable();
  for(i=0;i<NTCB;i++)
    if(strcmp(sender,tcb[i].name)==0)
      break;
    if(i==NTCB)
    {
      printf("error:sender not exist!\n");
      enable();
      return;
    }
    if(tcb[current].mq==NULL)
      return;
    p(&tcb[current].mutex);      /* 当前线程的消息缓冲队列资源的互斥操作*/
    buff=tcb[current].mq;
    tcb[current].mq=tcb[current].mq->next;
    for(i=0;i<buff->size;i++,a++)    /* 输出所接受的内容  */
       (*a)=buff->text[i];
    /*a=buff->next*/
    v(&tcb[current].mutex);  /* 当前线程的消息缓冲队列资源的互斥操作 */
    p(&mutexfb);
    buff->sender=-1;
    buff->size=0;
    strcmp(buff->text,"");
    buff->next=NULL;
    putbuf(buff);
    v(&mutexfb);
    p(&sfb);
    p(&tcb[current].sm);
    v(&test);     /* 对应于p(&Tcb[current].sm)  */
}


void main()
{
  InitInDos();
  InitTcb();
  freebuf=Initbuf();
  old_int8=getvect(8);

  strcpy(tcb[0].name,"main");
  tcb[0].state=RUNNING;
  tcb[0].value=0;
  current=0;
  Create("f1",(codeptr)f1,1024,5);
  Create("f2",(codeptr)f2,1024,6);
  tcb_state();
  /*setvect(8,new_int8);*/
  swtch();
  /*for(i=0;i<5000000;i++);*/
  while(!all_finished());
  tcb[0].name[0]='\0';
  tcb[0].state=FINISHED;
  setvect(8,old_int8);
  tcb_state();
  printf("\n Muli_task system teminated \n");
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -