【操作系统】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(®s, ®s, &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(®s, ®s, &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
- 【操作系统】Dos下的多任务系统
- 操作系统课程设计 基于DOS的多任务系统的实现
- DOS系统下的实时多任务系统开发(RTKERNEL)
- 基于dos的多任务系统实现
- DOS 下多任务系统的设计与实现 (1995-7)
- DOS多任务系统实现
- 基于DOS的多任务系统的实现
- 详析DOS操作系统下的磁盘结构
- dos系统下的常用命令
- dos下安装操作系统!
- 操作系统课程设计--基于线程的多任务系统的实现
- 实现纯 DOS下运行 多任务
- 《自己动手写操作系统》第三章pmtest8源码解析——多任务系统下的地址映射
- 多任务操作系统的任务切换
- 基于DOS的多任务系统的实现_杭电_2014
- DOS操作系统的历史
- 简单的多任务操作系统
- Java学习:1.Windows操作系统下的常用DOS命令
- 2.pppoe客户端宽带拨号
- 第五章结构图
- ubuntu 14.04 安装 Java 常用软件
- 关于如何使用控制台将mysql数据库进行导入和导出问题
- 火狐 IE 实现图片本地预览 demo
- 【操作系统】Dos下的多任务系统
- UITableViewRowAction详解(iOS8新API)
- Windows下多个版本Qt的安装配置
- PinnedHeaderListView在顶端不是屏幕顶端时title挤压失效的问题
- 黑马程序员-OC的核心语法
- C#基础学习笔记
- Struts2框架判断用户名是否已存在
- Activity的四种launchMode
- 题目1051:数字阶梯求和