基於DOS的多任務系統的實現_杭電_2014

本來想從網上隨便找段代碼應付一下老師,沒想到百度的代碼都是不完全(原因是老師驗收太鬆了),只能自力更生,將他修補完全.只寫了部分註解,後來實在寫不動了,可以參考指導書, 以後有空再加上去。

一共演示了兩個例子,一個利用pv操作實現讀者寫者問題,還有一個是線程通信。

用的編譯器是TC,就是實驗室的,用其他編譯器會報錯。運行一段時間會停止,按任意鍵即可繼續運行。


PV操作_讀者寫者問題

#include<dos.h>
#include<stdio.h>
#include<stdlib.h>
#define NTCB  10 /* 系統允許運行的最大線程數*/

/* 狀態碼常量定義*/
#define FINISHED 0 /* 表示線程處於終止態或TCB是空白狀態 */
#define RUNNING  1 /* 表示線程牌運行態 */
#define READY    2 /* 表示線程處於就緒 */
#define BLOCKED  3 /* 表示線程處於阻塞態 */
#define CLOCK_NUM 5   /* 每個線程所運行的時鐘數 */
#define NTEXT 1000  /* 消息長度 */
#define NBUFF 5     /* 空閒緩衝區最大數量 */

#define GET_INDOS 0x34
#define GET_CRIT_ERR 0x5d06
char far *indos_ptr =0;
char far *crit_err_ptr=0;
int current;      /* 當前進程tcb的下標 */
int timecount;     /* 時鐘中斷次數 */
typedef struct{
    int value;
    struct TCB *wq;/* 阻塞隊列首個TCB */
}semaphore;
struct buffer{
    int sender;         /* 消息發送者的內部標識 */
    int size;           /* 消息長度<=NTEXT個字節 */
    char text[NTEXT];   /* 消息正文 */
    struct buffer *next;/* 指向下一個消息緩衝區的指針 */
};
struct buffer *freebuf;/* 空閒緩衝區 */
semaphore mutexfb;
semaphore sfb;/*空閒緩衝區的信號量*/
semaphore full,empty,mutex;    /* 用於讀者寫者問題 */
int pro=0;/* 產品數量 */
struct TCB{
    unsigned char *stack ; /* 線程堆棧的起始地址*/
    unsigned ss; /* 堆棧段址 */
    unsigned sp;/* 堆棧指針 */
    char state ;/* 線程狀態 */
    char name[10];/*  線程的外部標識符 */
    struct TCB *next;  /* 下一個TCB指針 */

    /*以下三個變量用於線程通信*/
    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,       /*flags寄存器的允許中斷位*/
    off,seg;      /*撤銷線程代碼的偏移地址*/ /*撤銷線程代碼的段址*/
};
int DoBusy(void);
typedef int(far *codeptr)(void);
void interrupt swtch();
void InitDos(void);
int DoBusy(void);
void interrupt (*old_int8)(void);/*原來的時間中斷程序,需要先聲明*/
void TCBState();
void mySleep();
void interrupt new_int8(){/* 一次時鐘中斷的時間爲55ms */
    int i;
    timecount++;

    (*old_int8)();
    if(DoBusy())
        return ;
     if(timecount<CLOCK_NUM)
        return ;
     disable();
     timecount=0;
     tcb[current].ss=_SS; /* 保存當前線程信息 */
     tcb[current].sp=_SP;
     tcb[current].state=READY;

     for(i=1;i<NTCB;i++){    /* 尋找一個就緒的進程 */
         if(tcb[(i+current)%NTCB].state==READY)
            break;
     }
     current=(i+current)%NTCB;
     _SS=tcb[current].ss;
     _SP=tcb[current].sp;
     tcb[current].state=RUNNING;
     printf("current thread=%d\n",current);
     enable();
}
void over(void){ /* 線程結束後的處理工作 */
    disable();
    free(tcb[current].stack);
   /* strcpy(tcb[current].name,"");*/
    tcb[current].state=FINISHED;
    swtch();     /* 選擇一個新的線程進行工作 */
    enable();
}
void destroy(int threadID){
    if(threadID==current)/* 不允許撤銷自己 */
        return ;
    tcb[current].state=FINISHED;
    free(tcb[threadID].stack);
    strcpy(tcb[threadID].name,"");
 }
 void InitSem(semaphore *sem,int value){
    sem->wq=NULL;
    sem->value=value;
}
int  isFinished(){    /* 判斷除主線程外的其他線程是否已經完成 */
   int i;
   for(i=1;i<NTCB;i++){
        if(tcb[i].state!=FINISHED )
            return 0;
    }
    return 1;
}
int create(char *name,codeptr code,int stackLen){  /* 創建線程 */
    int i;
    char *p;
    struct int_regs *pt;
    for(i=1;i<NTCB;i++){
        if(tcb[i].state==FINISHED)
            break;
    }
    if(i==NTCB)
        return -1;
     p=(char *)malloc(stackLen*sizeof(char)); /* 申請堆棧空間 */
     p=p+stackLen;

     pt=(struct int_regs*)p;
     pt--;

     pt->flags=0x200;
     pt->cs=FP_SEG(code);
     pt->ip=FP_OFF(code);
     pt->ds=_DS;
     pt->es=_ES;
     pt->off=FP_OFF(over);
     pt->seg=FP_SEG(over);

     strcpy(tcb[i].name,name);
     tcb[i].state=READY;
     tcb[i].stack=p-stackLen;
     tcb[i].ss=FP_SEG(pt);
     tcb[i].sp=FP_OFF(pt);

     return i;
}
void interrupt swtch(){
    int i;
    disable();
     tcb[current].ss=_SS;
     tcb[current].sp=_SP;
    for(i=0;i<NTCB;i++){
         if(tcb[(i+current)%NTCB].state==READY)
            break;
     }
     current=(i+current)%NTCB;
     _SS=tcb[current].ss;
     _SP=tcb[current].sp;
     tcb[current].state=RUNNING;
      printf("current thread=%d\n",current);
     enable();
 }
 void InitTCB(){
    int i;
    struct buffer *tmp;
    for(i=0;i<NTCB;i++){
        tcb[i].state=FINISHED;
        tcb[i].stack=NULL;
        InitSem(&tcb[i].mutex,1);
     }
     current=0;
     timecount=0;
    mutexfb.value=1;mutexfb.wq=NULL;
    sfb.value=NBUFF;sfb.wq=NULL;
    freebuf=(struct buffer *)malloc(sizeof(struct buffer));
    for(i=1,tmp=freebuf;i<NBUFF;i++){
        tmp->next=(struct buffer *)malloc(sizeof(struct buffer));
        tmp=tmp->next;
        tmp->next=NULL;
    }
    
 }

 void block(struct TCB **pptcb){
    struct TCB *tmp;
    disable();
    tcb[current].state=BLOCKED;
    if(*pptcb==NULL)
        *pptcb=&tcb[current];
    else{
        tmp=*pptcb;
        while(tmp->next!=NULL){
            tmp=tmp->next;
         }
         tmp->next=&tcb[current];
     }
     swtch();
     enable();
 }
 void wakeup(struct TCB **pptcb){
     disable();
     if(*pptcb==NULL)
        return ;
     (*pptcb)->state=READY;
     *pptcb=(*pptcb)->next;
     enable();
 }
  void p(semaphore *sem){
     struct TCB **qp;
     disable();
        sem->value=sem->value-1;
       /*  printf("sem->value=%d\n",sem->value); */
        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;
       /*  printf("sem->value=%d\n",sem->value); */
        if(sem->value<=0)
            wakeup(qp);
     enable();
 }
struct buffer *getbuf(void){
    struct buffer *buff;
    buff=freebuf;
    freebuf=freebuf->next;
    return(buff);
}
void insert(struct buffer **mq,struct buffer *buff){
    struct buffer *temp;
    if(buff==NULL) return ;
    buff->next=NULL;
    if(*mq==NULL)
        *mq=buff;
     else{
         temp=*mq;
         while(temp->next!=NULL)
         temp=temp->next;
         temp->next=buff;
     }
 }
 void send(char *receiver,char *a,int size){
     struct buffer *buff;
     int i,id=-1;
     disable();
     for(i=0;i<NTCB;i++){
         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);
    v(&tcb[id].mutex);
    v(&tcb[id].sm);
    enable();
}
struct buffer* remo(struct buffer **mq,int sender){
        int i,j;
    struct buffer *front,*rear;
    front=*mq;rear=*mq;
    while(front!=NULL){
        if(front->sender==sender)
        break;
        rear=front;
        front=front->next;
    }
    if(front==*mq)
        *mq=(*mq)->next;
    else
        rear->next=rear->next->next;
    return front;
}
int receive (char *sender,char *str){
    struct buffer *buff,*tmp;
    int i,id;
    disable();
    for(i=0;i<NTCB;i++){
       /*  printf("sender=%s,tcb[i].name=%s\n",sender,tcb[i].name); */
        if(strcmp(sender,tcb[i].name)==0){
            id=i;
            break;
        }
    }
    if(id==-1){
        printf("Eooro:Receiver not exist!!\n");
        enable();
        return ;
    }
   /*  printf("threa2 find id=%d\n",id); */
    p(&tcb[current].sm);
    p(&tcb[id].mutex);
       buff=remo(&(tcb[current].mq),id);
    v(&tcb[id].mutex);
   /*  printf("get message succes\n"); */
    for(i=0;i<buff->size;i++)
        str[i]=buff->text[i];
    buff->next=NULL;
    if(freebuf==NULL)
        freebuf=buff;
     else{
        tmp=freebuf;
        while(tmp->next!=NULL){
            tmp=tmp->next;
        }
        tmp->next=buff;
    }
    v(&sfb);
    enable();
}


int fun1(void){
    while(1){
         p(&empty);
         p(&mutex);
          pro++;
          printf("producer product a product pro=%d\n",pro);
           v(&mutex);
        v(&full);
        mySleep();

    }
}
 int fun2(void){
    while(1){
         p(&full);
         p(&mutex);
          pro--;
          printf("consumer use a product pro=%d\n",pro);
          v(&mutex);
        v(&empty);
        mySleep();
    }
}

int main(){
    int n=0,k1,k2,k3=0;
    InitTCB();
    InitDos();
    InitSem(&full,0);
    InitSem(&empty,3);
    InitSem(&mutex,1);
    old_int8=getvect(8);  /* 獲取系統原來的時鐘中斷服務程序的入口地址 */
    strcpy(tcb[0].name,"main");
    tcb[0].state=RUNNING;
    create("fun1",fun1,1024);
    create("fun2",fun2,1024);
    setvect(8,new_int8);
    while(!isFinished()){
        for(k1=0;k1<=20000;k1++)
            for(k2=0;k2<=10000;k2++);
        /* printf("MainThread is Running \n"); */
        k3++;
        if(k3%5==0)
            getch();

     }
    setvect(8,old_int8);
    printf("all threads is finished\n");
    getch();
}
void TCBState(){
    int i;
    for(i=0;i<3;i++){
        printf("thread name=%s,Id=%d,state=%d\n",tcb[i].name,i,tcb[i].state);
    }
}
void InitDos(void){
    union REGS regs;
    struct SREGS segregs;
    regs.h.ah=GET_INDOS;
    intdosx(&regs,&regs,&segregs);
    indos_ptr=MK_FP(segregs.es,regs.x.bx);
    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);
       }
}
int DoBusy(void){
    if(indos_ptr&&crit_err_ptr)
        return (*indos_ptr||*crit_err_ptr);
     else
        return -1;
}
void mySleep(){
    int k1,k2;
     for(k1=0;k1<=20000;k1++)
            for(k2=0;k2<=10000;k2++);
}


運行結果



線程通信

將fun1,fun2改下就可以了,功能都已經在上面的代碼實現了,fun1,fun2只是一個演示。

int fun1(void){
    int i,k1,k2;
    char sendStr[30];
    printf("thread1 start to send message\n");
    for(i=0;i<10;i++){
        sprintf(sendStr,"this is %d message from thread1",i);
        send("fun2",sendStr,strlen(sendStr)+1);
        printf("thread1 send message %d\n",i);
        mySleep();
    }
    printf("thread1 send meesage over\n");

}
int fun2(void){
    int i;
    char recStr[30];
    for(i=0;i<10;i++){
        receive("fun1",recStr);
        printf("%s   \n",recStr);
        mySleep();
         mySleep();
    }
}

運行結果



轉載請標明出處,原文http://blog.csdn.net/ccy0815ccy


發佈了37 篇原創文章 · 獲贊 7 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章