基于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++);
}


运行结果

基于DOS的多任务系统的实现_杭电_2014_第1张图片


线程通信

将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();
    }
}

运行结果

基于DOS的多任务系统的实现_杭电_2014_第2张图片


转载请标明出处,原文http://blog.csdn.net/ccy0815ccy


你可能感兴趣的:(线程,dos,操作系统,杭电)