【操作系统】Dos下的多任务系统

来源:互联网 发布:网络台球 编辑:程序博客网 时间:2024/04/28 05:13

操作系统的课程设计作业之一,想想当初关于这段代码被老师拷问成了狗,简直是生命不能承受之重啊.如果有学弟选择了周旭老师的操作系统,我唯一能帮助你的就是代码拿过去用.还有他是个好老师.


代码必须在Turbo C2.0环境下运行,因为需要用到interupt关键字.

#include <dos.h>#include <stdlib.h>#include <stdio.h>#include <string.h>/*** #include "indos.c"** #include "exterr.c"*/#define GET_INDOS 0X34           /*未公开的34h号系统功能调用,可得到INDOS标志的地址(由ES:BX返回)*/#define GET_GRIT_ERR 0X5D06#define NTCB 5                   /*系统允许的最多任务数*/#define NTEXT 20                 /*消息字符串的最大长度*/#define NBUF  5                  /*缓冲队列的最大长度*//* state code *//* null0not assigned */#define FINISHED        0       /*线程的状态标志 */#defineRUNNING        1       /*线程的状态标志 */#define READY         2       /*线程的状态标志 */#define BLOCKED         3       /*线程的状态标志 */#define NAME_MAX        10      /*线程外部标识符的最大长度*//*unsigned oldss;unsigned oldsp;*/static int current = 0;/* 当前正在执行程序的内部标志符 */int multstop = 1;       /*  */int timecount = 0;      /*记录当前线程从上次调度至今已经运行了多少时钟中断间隔 单位 1/18.2second*/int TL;                 /*时间片的大小*/int n = 0;int buf1;char far *indos_ptr = 0 ;           /*存放INDOS标志的地址*/char far *crit_err_ptr = 0 ;        /*存放严重错误标志的地址*//* the pointer to the process's code  */typedef int (far *codeptr)(void);typedef struct{        int value;        struct TCB *wq;      /*  */} semaphore;semaphore mutexfb = {1, NULL};            /* 消息缓冲队列的互斥信号量 */semaphore sfb = {NBUF, NULL};             /* 消息缓冲队列的计数信号量 */semaphore mutex = {1, NULL};              /* 接收队列的消息队列的互斥信号量 */semaphore sa = {1, NULL};                 /* */semaphore sb = {0, NULL};struct buffer{        int id;        int size;        char text[NTEXT];        struct buffer *next;} buf[NBUF], *freebuf;             /*freebuf:空闲缓冲队列(是一临界资源)*/struct TCB{        int priority;           /* 线程的优先级 0~10 */        int id;                 /* 每个线程的唯一的内部标识符 */        unsigned sp;        unsigned ss;        unsigned int *chan;             /* event process is awaiting */        struct buffer *mq;        semaphore mutex;        semaphore sm;                   /* 接受线程的消息队列的计数信号量,用于实现同步 */        struct TCB *next;               /* link pointer */        char name[NAME_MAX];        /* 每个进程的外部标识符 */        unsigned char *stack;           /* 堆栈的起始地址 */        char state;                     /* 线程的状态 */} tcb[NTCB] ;/* the registers pushed in the stack after entering an interrupt funtion */struct int_regs{        unsigned bp;        unsigned di;        unsigned si;        unsigned ds;        unsigned es;        unsigned dx;        unsigned cx;        unsigned bx;        unsigned ax;        unsigned ip;        unsigned cs;        unsigned flags;        unsigned off;        unsigned seg;};void interrupt (*old_int8)(void);           /*函数指针*/void interrupt new_int8(void);              /*函数:解决因时间片到时引起的调度*/int create(char *name, codeptr code, int stck, int priority_num);/*创建一个线程,让其执行code开始的代码*/void destroy(int id);            /*撤销一个线程*/void over(void);/*如果是当前线程运行完成而引起现场给你撤销,则系统能自动撤销该线程,并重新进行CPU调度,先调用destroy()*/void interrupt swtch(void);     /*调度程序函数:(原因)1.线程执行完毕 2.阻塞*/int all_finished(void);         /*检查系统中除了0#线程以外的所有其他线程是否都已经运行完成,是返回1,否返回0*/void free_all(void);            /*把TCB数组全部释放掉*/void tcb_state(void);           /*输出所有的线程的当前状态信息*/void InitTcb(void);             /*创建空白的TCB数组并初始化*/int DosBusy(void);              /*判断是否DOS忙*/void block(unsigned *chan, struct TCB **qp);void free_all(void);struct buffer *getbuf(void);       /* 获取空闲缓冲区函数 */void init_buf(void);void InitInDos(void);void insert(struct buffer **mq, struct buffer *buff);     /* 插入缓冲区到缓冲队列函数 */void interrupt new_int8(void);      /* 调度程序的函数:解决因时间片到时引起的调度(通过截断时钟中断int08)*/void over(void);void p(semaphore *sem);void p(semaphore *sem);int receive(char *sender,char *b);      /* 接受原语 */void receiver(void);struct buffer *remov(struct buffer **mq, int sender);   /* 获取消息缓冲区队列函数 */void sender(void);void interrupt swtch(void);void wakeup_first(struct TCB **qp);void f1(void);void f2(void);void f3(void);void f4(void);void f5(void);void f6(void);void cp(void);void cp1(void);void iop(void);void iop1(void);int main(void){        int temp;       //这个变量用来存储create函数的返回值,从而判断create是否成功int sele = -1;             //selection:选择对应操作的序号char name[NAME_MAX];InitInDos();               /*获得INDOS标志的地址和严重错误标志的地址*/InitTcb();old_int8 = getvect(8);     /*获取系统原来的INT08H的中断服务程序的入口地址*//* 创建 #0# 号进程 */strcpy(tcb[0].name, "main");tcb[0].state = RUNNING;current = 0;for(; sele;){do{clrscr();printf("\n\n\n\t***********************************************************\n");printf("\t* 0.退出多任务系统:                               *\n");printf("\t* 1.线程的\"顺序\"执行:                      *\n");printf("\t* 2.线程的并发执行:                    *\n");printf("\t* 3.线程同时共享临界资源: *\n");printf("\t* 4.线程互斥共享临界资源: *\n");printf("\t* 5.线程没做好同步时情况:                  *\n");printf("\t* 6.线程同步时的情况:                       *\n");printf("\t* 7.线程间的通信:                          *\n");printf("\t***********************************************************\n\n");printf("\t 请输入对应的数字(0-7):");scanf("%d", &sele);}while(sele<0 || sele>7) ;switch(sele){case 1:temp = create("f1", (codeptr)f1, 1024, 5);if(temp == -1)                        {                                printf("创建线程失败!\n");                                exit(EXIT_FAILURE);                        }temp = create("f2", (codeptr)f2, 1024, 6);if(temp == -1)                        {                                printf("创建线程失败!\n");                                exit(EXIT_FAILURE);                        }clrscr();printf("\t 不剥夺方式下两个线程的并发执行 \n");printf("\t 其中线程f1不断输出字母a,共1000次 ;\n");printf("\t 而线程f2不断输出字母b,共100次 ;\n");printf("\t 按任意键继续!\n");getch();swtch();/*输出*/break;case 2:temp = create("f1", (codeptr)f1, 1024, 5);if(temp == -1)                        {                                printf("创建线程失败!\n");                                exit(EXIT_FAILURE);                        }temp = create("f2", (codeptr)f2, 1024, 6);if(temp == -1)                        {                                printf("创建线程失败!\n");                                exit(EXIT_FAILURE);                        }clrscr();printf("\t 时间片轮转方式下两个线程的并发执行\n");/**/printf("\t 其中线程f1不断输出字母a,共1000次;\n");/**/printf("\t 而线程f2不断输出字母b,共100次。\n");/**/printf("\t 请设置时间片的大小(单位为1/18.2秒):");/**/scanf("%d", &TL);printf("\t 按任意键继续!\n");getch();setvect(8, new_int8);swtch();break;case 3:n = 0;temp = create("f3", (codeptr)f3, 1024, 5);if(temp == -1)                        {                                printf("创建线程失败!\n");                                exit(EXIT_FAILURE);                        }temp = create("f4", (codeptr)f4, 1024, 6);if(temp == -1)                        {                                printf("创建线程失败!\n");                                exit(EXIT_FAILURE);                        }clrscr();printf("\t 线索同时共享临界资源的情况\n");/* */printf("\t 线程f3和f4共享一变量n;\n");/**/printf("\t times线程f3不断对n进行加1操作,共进行100次;\n"); /**/printf("\t 线程f4也不断对n进行加1操作,共进行100次;\n");/**/printf("\t 因此,最后n的值应为200\n");/**/printf("\t 按任意键继续!\n");getch();TL = 1;setvect(8, new_int8);swtch();break;case 4:n = 0;temp = create("f3", (codeptr)f5, 1024, 5);if(temp == -1)                        {                                printf("创建线程失败!\n");                                exit(EXIT_FAILURE);                        }temp = create("f4", (codeptr)f6, 1024, 6);if(temp == -1)                        {                                printf("创建线程失败!\n");                                exit(EXIT_FAILURE);                        }clrscr();printf("\t 线程互斥共享临界资源: \n");printf("\t 线程f3和f4共享一变量n;\n");printf("\t 线程f3不断对n进行加1操作,共进行100次\n");printf("\t 线程f4也不断对n进行加1操作,共进行100次\n");printf("\t 因此,最后n的值应为200\n");TL=1;printf("\t 按任意键继续!\n");getch();setvect(8,new_int8);swtch();break;case 5:n = 0;create("iop", (codeptr)iop1, 1024, 5);create("cp", (codeptr)cp1, 1024, 6);clrscr();printf("\t 没同步的计算进程和输出进程的并发执行 \n");printf("\t 并将其放入一缓冲区\n");printf("\t 打印进程iop依次取出cp放入缓冲区中的数,将它输出出来\n");printf("\t 本例中,cp计算出十个数,分别为0,1,2,3,4,5,6,7,8,9\n");printf("\t 按任意键继续!\n");getch();TL = 1;setvect(8, new_int8);swtch();break;case 6:n = 0;create("iop", (codeptr)iop, 1024, 5);create("cp", (codeptr)cp, 1024, 6);clrscr();printf("\t 经过同步的计算进程和输出进程的并发执行:\n");printf("\t 计算进程cp不断计算数,并将其放入一缓冲区,\n\n");printf("\t 打印进程iop依次取出cp放入缓冲区中的数,将它输出出来.\n");printf("\t 本例中,cp计算出十个数,分别为0,1,2,3,4,5,6,7,8,9\n");printf("\t 按任意键继续!\n");getch();TL = 1;setvect(8,new_int8);swtch();break;case 7:init_buf();n = 0;create("sender", (codeptr)sender, 1024, 5);create("receiver", (codeptr)receiver, 1024, 6);printf("\t 线程间的通信:\n");printf("\t 线程sender调用send原语向线程receiver发送十个消息\n");printf("\t 十个消息的内容分别为message0......message9\n");printf("\t 线程receiver调用receive接收sender发来的消息\n");printf("\t 本例中,消息缓冲的个数为5个\n");printf("\t 按任意键继续!\n");getch();TL = 1;setvect(8, new_int8);swtch();break;default:sele = 0;            }            while(!all_finished())            {                    NULL;            }            if(sele == 3)            {    printf("因对临界资源的共享没互斥,本次运行的结果为\n");    printf("n==%d\n", n);            }            if(sele == 4)    {        printf("n==%d\n",n);    }            if(sele != 0)            {    printf("除0号线程外,其余线程都已执行完毕,请按任意键结束!\n");    getch();            }            setvect(8, old_int8);        }        printf("\t\t多任务系统结束运行\n");        return 0;}int DosBusy(void)                   /*判断是否DOS忙*/{        if(indos_ptr && crit_err_ptr)        {                return   (*indos_ptr || *crit_err_ptr);        }        else        {                return(-1);        }}                  /*用于判断当前DOS是否处于繁忙状态*/void InitInDos(){        union   REGS   regs;        struct   SREGS   segregs;        regs.h.ah = GET_INDOS;         /*使用34H号系统功能调用*/        intdosx(&regs, &regs, &segregs);        indos_ptr = MK_FP(segregs.es, regs.x.bx);        if(_osmajor < 3)        {                crit_err_ptr = indos_ptr + 1;       /*严重错误在INDOS后一字节处*/        }        else        {                if(_osmajor==3 && _osmajor==0)                {                        crit_err_ptr = indos_ptr - 1;       /*严重错误在INDOS前一字节处*/                }                else                {                        regs.x.ax = GET_GRIT_ERR;                        intdosx(&regs, &regs, &segregs);                        crit_err_ptr = MK_FP(segregs.ds, regs.x.si);                }        }}                       /*初始化DOS,取得INDOS标志和严重错误标志地址*/void InitTcb(void){        int i;        for(i=0; i<NTCB; i++)        {                tcb[i].priority = -1;                tcb[i].stack = NULL;                tcb[i].state = FINISHED;                tcb[i].chan = NULL;                tcb[i].name[0] = '\0';                tcb[i].next = NULL;                tcb[i].mq = NULL;                tcb[i].mutex.value = 1;                tcb[i].mutex.wq = NULL;                tcb[i].sm.value = 0;                tcb[i].sm.wq = NULL;        }}int create(char *name,codeptr code,int stck, int priority_num){        struct int_regs far *r;        /*指针*/        int i;        int id = -1;        unsigned char *ptr;        for(i=0; i<NTCB; i++)        {                if(tcb[i].state == FINISHED)                {                        id = i;                        break;                }        }        if(id == -1)        {                return id;  /*若创建失败,则返回-1*/        }        disable();        tcb[id].stack = (unsigned char *)malloc(stck);        memset(tcb[id].stack, 0, stck);        r = (struct int_regs *)(tcb[i].stack + stck - 1);        r--;        tcb[id].ss = FP_SEG(r);        tcb[id].sp = FP_OFF(r);        r->cs = FP_SEG(code);        r->ip = FP_OFF(code);        r->ds = _DS;      /*DS和ES为CPU的寄存器*/        r->es = _DS;        r->flags = 0x200;         //512  ??????????        r->seg = FP_SEG(over);      /*over is a function pointer  ,FP_SEG(p), 得到该地址的段地址*/        r->off = FP_OFF(over);      /*over is a function pointer  ,FP_OFF(p), 得到该地址的段内偏移,MK_FP(seg,off)得到对应的指针*/        tcb[id].state = READY;        for(i=0; i<NAME_MAX; i++,name++)        {                if((tcb[id].name[i] = *name) == NULL)                {                        break;                }        }        tcb[id].priority = priority_num;        tcb[id].name[NAME_MAX - 1] = '\0';        enable();        return(id);}void destroy(int id){        disable();        free(tcb[id].stack);        tcb[id].stack = NULL;           /*把指针指向NULL,防止野指针的生成*/        tcb[id].state = FINISHED;        printf("\n **** Thread %s is terminated ****\n", tcb[id].name);        tcb[id].name[0] = '\0';        enable();}void over(void){        destroy(current);        swtch();}void block(unsigned *chan, struct TCB **qp){        int id;        struct TCB *tcbp;        id = current;        tcb[id].state = BLOCKED;        tcb[id].chan = chan;        if((*qp) == NULL)        {                (*qp) = &tcb[id];        }        else        {tcbp = *qp;while(tcbp->next != NULL){tcbp = tcbp->next;}tcbp->next = &tcb[id];        }tcb[id].next = NULL;swtch();}void wakeup_first(struct TCB **qp){        int i;        struct TCB *tcbp;        if((*qp) == NULL)        {                return;        }        tcbp = (*qp);        (*qp) = (*qp)->next;        tcbp->state = READY;        tcbp->chan = NULL;        tcbp->next = NULL;}void p(semaphore *sem){        struct TCB **qp;        disable();        sem->value = sem->value - 1;        if(sem->value < 0)        {                qp = &(sem->wq);           // **ask**                block((unsigned *)sem, 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();}/*  该函数主要解决两种原因引起的调度:**  1.线程执行完毕**  2.正在执行的线程因等待某事件发生而不能继续执行*/void interrupt swtch(void){        int loop = 0;        disable();/* save the old process */        tcb[current].ss = _SS;        tcb[current].sp = _SP;        if(tcb[current].state == RUNNING)        {tcb[current].state = READY;        }/* find a new process and restore it */if(++current == NTCB){                current = 0;}while(tcb[current].state!=READY && loop++<NTCB-1){current++;if(current == NTCB){                        current = 0;}}if(tcb[current].state != READY)        {                current = 0;        }_SS = tcb[current].ss;_SP = tcb[current].sp;tcb[current].state = RUNNING;timecount = 0;/* tcb_state();*/enable();}int all_finished(void){int i;for(i=1; i<NTCB; i++)        {if(tcb[i].state != FINISHED)                {                        return(0);                }return(1);        }}void free_all(void){int i;for(i=0; i<NTCB; i++){if(tcb[i].stack){tcb[i].name[0] = '\0';tcb[i].state = FINISHED;free(tcb[i].stack);tcb[i].stack = NULL;          /*防止野指针的产生*/}}}void interrupt new_int8(void)      /*调度程序的函数:解决因时间片到时引起的调度(通过截断时钟中断int08)*/{int loop = 0;(*old_int8)();if(++timecount < TL)        {                return;        }if(DosBusy())        {                return;        }disable();tcb[current].ss = _SS;tcb[current].sp = _SP;if(tcb[current].state == RUNNING)        {tcb[current].state = READY;        }/* find a new process and restore it */if(++current == NTCB)        {                current = 1;        }while(tcb[current].state!=READY && ++loop<NTCB-1){current++;if(current == NTCB)                {                        current=1;                }}if(tcb[current].state != READY)        {                current=0;        }_SS = tcb[current].ss;_SP = tcb[current].sp;tcb[current].state = RUNNING;timecount = 0;/*    tcb_state();*/enable();}void tcb_state(void){int i;/*if(!multstop) return;*/printf("\n");for(i=0; i<NTCB; i++){printf("proc %d(%9s):  ",i, tcb[i].name);switch(tcb[i].state){case READY:printf("READY\n");break;case RUNNING:printf("RUNNING\n");break;case FINISHED:printf("FINISHED\n");break;case BLOCKED:printf("BLOCKED\n");break;}}}void init_buf(void){int i;for(i=0; i<NBUF-1; i++)        {buf[i].next = &buf[i+1];        }buf[i].next = NULL;freebuf = &buf[0];}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;}}struct buffer *remov(struct buffer **mq, int sender)   /* 获取消息缓冲区队列函数 */{struct buffer *p;struct buffer *q;struct buffer *buff;q = NULL;p = *mq;while((p->id != sender) && (p->next != NULL)){q = p;p = p->next;}if(p->id == sender){buff = p;if(q == NULL)                {                        *mq = buff->next;                }else{                        q->next = buff->next;}buff->next = NULL;return(buff);}else{return(NULL);}}void send(char *receiver, char *a, int size)      /* 发送原语 */{struct buffer *buff;int i;int id = -1;disable();for(i=0; i<NTCB; i++){if(strcmp(receiver,tcb[i].name) == 0){id = i;break;}}if(id == -1){enable();return;}p(&sfb);p(&mutexfb);buff = getbuf();v(&mutexfb);buff->id = 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();}int receive(char *sender,char *b)      /* 接受原语 */{int i;int size;int id = -1;struct buffer *buff;disable();for(i=0; i<NTCB; i++){if(strcmp(sender,tcb[i].name) == 0){id = i;break;}}if(id == -1){enable();return(0);}p(&tcb[current].sm);p(&tcb[current].mutex);buff = remov(&(tcb[current].mq), id);v(&tcb[current].mutex);if(buff == NULL){v(&tcb[current].sm);enable();return(-1);}size = buff->size;for(i=0; i<buff->size; i++, b++){                *b = buff->text[i];}p(&mutexfb);insert(&freebuf, buff);v(&mutexfb);v(&sfb);enable();return(size);}/*codeptr lookup(char *name){int i;  for(i=0;i<NTCB;i++){  strcmp(name,table[i].name)==0)  return(table[i].code);  }  return(NULL);  }*/void f1(void){long i;long j;long k;for(i=0; i<1000; i++){putchar('a');for(j=0; j<1000; j++){for(k=0; k<100; k++)                        {                                NULL;                        }}}}void f2(void){long i;long j;long k;for(i=0; i<100; i++){putchar('b');for(j=0; j<1000; j++){for(k=0; k<100; k++)                        {                                NULL;                        }                }}}/*int n=0;*/void f3(void){long i;long j;long k;int temp;for(i=0; i<100; i++){temp = n;delay(5);temp++;n = temp;for(j=0; j<1000; j++){for(k=0; k<99; k++)                        {                                NULL;                        }}}}void f4(void){long i;long j;long k;int temp;for(i=0; i<100; i++){temp = n;temp++;delay(10);n = temp;for(j=0; j<1000; j++){for(k=0; k<100; k++)                        {                                NULL;                        }}}}/*semaphore mutex={1,NULL};*/void f5(void){long i;long j;long k;int temp;for(i=0; i<100; i++){p(&mutex);temp = n;delay(5);temp++;n = temp;v(&mutex);for(j=0; j<1000; j++){for(k=0; k<99; k++)                        {                                NULL;                        }}}}void f6(void){long i;long j;long k;int temp;for(i=0; i<100; i++){p(&mutex);temp = n;temp++;delay(10);n = temp;v(&mutex);for(j=0; j<1000; j++){for(k=0; k<100; k++)                        {                                NULL;                        }}}}/* int buf1;** semaphore sa={1,NULL},sb={0,NULL};*/void cp1(void){int i;for(i=0; i<10; i++){n++;buf1 = n;}}void iop1(void){int i;int tem;for(i=0; i<10; i++){tem = buf1;printf("Out %d:%d\n", i, tem);}}void cp(void){int i;for(i=0; i<10; i++){n++;p(&sa);buf1 = n;v(&sb);}}void iop(void){int i;int tem;for(i=0; i<10; i++){p(&sb);tem = buf1;v(&sa);printf("Out %d:%d\n", i, tem);}}void sender(void)           /* 发送线程的外部标识符 */{int i;int j;char a[10];loop:for(i=0; i<10; i++){strcpy(a, "message");a[7] = '0' + n;a[8] = 0;send("receiver", a, strlen(a));printf("sender:Message \"%s\"  has been sent\n", a);n++;}receive("receiver", a);if (strcmp(a, "ok") != 0){printf("Not be committed,Message should be resended!\n");/*接收进程没确认,需重新发送消息*/goto loop;}else        {                printf("Committed,Communication is finished!\n"); /*发送者得到接收者的确认,通信结束*/        }}void receiver(void)         /* 接受线程的外部标识符的指针 */{int i;int j;int size;char b[10];for(i=0; i<10; i++){b[0] = 0;while((size=receive("sender", b)) == -1);{                        printf("receiver: Message is received--");/*已接收到消息--*/}for(j=0; j<size; j++){putchar(b[j]);}printf("\n");}strcpy(b, "ok");send("sender", b, 3);/* 发送确认消息 */}


0 0
原创粉丝点击