基于DOS的多任务系统的实现_杭电_2014

来源:互联网 发布:js prototype 继承 编辑:程序博客网 时间:2024/04/27 21:58

本来想从网上随便找段代码应付一下老师,没想到百度的代码都是不完全(原因是老师验收太松了),只能自力更生,将他修补完全.只写了部分注解,后来实在写不动了,可以参考指导书, 以后有空再加上去。

一共演示了两个例子,一个利用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 0x5d06char 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


0 0