




已阅读5页,还剩16页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
杭州电子科技大学操作系统课程设计课程设计题目: 基于DOS的多任务系统实现姓名:xxx班级:xx学号:xx学院:计算机学院专业:网络工程负责老师:贾刚勇完成日期:2015-6-9基于DOS的多任务系统的实现一, 课程设计的目的通过对线程(和进程)的创建和撤销,CPU的调度,同步机制,通信机制的实现,以达到一下目的:1, 加深对线程和进程概念的理解,明确进程和程序的区别。2, 加深对CPU调度过程(现场保护,CPU的分派和现场的恢复)的理解。3, 进一步认识并执行的概念,明确顺序执行和并发执行的区别。4, 加深对临界资源,临界区,信号量以及同步机制的理解。5, 加深对消息缓冲通信的理解。二, 设计要求1, 用C语言完成线程的创建和撤销,并按优先权加时间片轮转算法对多线程进行调度。2, 改变时间片的大小,观察结果的变化,3, 假设两个线程共用同一软件资源(如某以变量,或者某以数据结构),请用记录型信号量来实现对它的互斥访问。4, 假设有两个线程共享一个可以存放5个整数的缓冲,一线程不停地计算1至50的平方,并将结构放入缓冲中,另一个线程不断地从缓冲中取出结果,并将它们打印出来,请用记录型信号量实现这一生产者和消费者的同步问题。5, 实现消息缓冲通信,并与3,4中的简单通信进行比较。三, 程序设计思想以及总流程图1, 程序的设计思想:该程序主要是分5大块内容:线程的创建和撤销,线程的调度,线程的同步与互斥,线程的阻塞与唤醒,利用消息缓冲队列的线程间的通信。由这五大块功能来完成的基于DOS的多任务系统的实现。在这个系统中,首先先由main函数进行一些初始化工作,然后直接创建0#线程对应于main函数,再由0#线程调用create创建1#,2#线程分别对应与函数f1(),f2(),最后将系统的中断服务程序设置为new_int8,并把控制交给1#线程,启动多个线程的并发执行。0#线程是一个比较特殊的线程,它在创建的时候没有使用create来创建,而是在系统初始化后直接创建的,因它对应的程序段为main函数中的一段,所以也直接使用整个系统的堆栈,而不再创建时为私有堆栈分配额外的空间;同样,撤销的时也不需要释放私有堆栈的空间,所以也没有over()函数而是直接撤销,从这方面来看,它是一个系统线程。此外,在启动多个线程并发执行过程后,0#线程将系统控制权转交出去,直至系统中其他进程都不具备执行条件时,它才有可能重新得到CPU,从这方面看,0#线程相当于是一个空转线程,最后,0#线程还担负着一个特别的使命:等待系统中所有其他的线程的完成,此时,它将直接撤销自己并恢复原来的时钟中断服务程序,从此终止整个多任务系统。2, 系统的总流程图 四, 系统各个功能的实现思想1, 线程的创建和撤销线程的创建过程关键就是对私有堆栈和TCB初始化的过程,其过程如下:i, 为新线程分配一空闲的线程控制块ii, 为新线程的私有堆栈分配内存空间(因为对等线程共享程序段和数据段空间,所以创建线程时不必像创建进程那样再为程序段和数据段分配内存空间)iii, 初始化新线程的私有堆栈,即按CPU调度时现场信息的保存格式布置堆栈。iv, 初始化线程控制块,即填入线程的外部标识符,设置好线程私有堆栈的始址,段址和栈顶指针,将线程的状态置为就绪状态。v, 最后哦返回新线程的内部标识符vi, 线程的内存映像如下:线程的撤销过程中,一个关键的地方是在初始化线程私有堆栈时 需要将over()的入口地址压入线程的私有堆栈中,这样做的好处是:当线程所对应的函数正常结束时,over()函数的入口地址将最为函数的返回地址被弹出至CS,IP寄存器,那么控制将自动转向over(),从而使对应的线程被自动撤销,并重新进行CPU调度。2, 线程的调度引起CPU调度原因主要是有三种情况:时间片到时,线程执行完毕或正在执行的线程因等待某种事件而不能继续执行。由这些原因,调度程序可以通过两个函数分别处理不同原因引起的调度:New_int8()函数主要是处理因时间片到时引起的调度该调度可以通过截取时钟中断(int 08)来完成;Swtch()函数主要是处理因其他原因引起的调度;New_int8()函数因为是通过截取时钟中断来实现,可以知道其是属于系统调度,由于涉及到系统调度的函数 都是需要对DOS状态进行判断,以防止出现系统数据混乱等情况的发生(从Dos的不可重入性来得出),而Swtch()函数是处理因其他原因引起的调度,所以它所涉及到的仅仅是用户级的函数调度,没有涉及到系统级的函数调度,因此Swtch()函数不需要对Dos状态进行判断。对于线程的两种调度函数的过程,因其相似,给出New_int8()函数的执行过程图,如下:需要主要的是:新的时钟中断处理程序不能太长,否则系统效率将大大下降甚至使系统无法正常工作;在新的时钟中断处理程序必须调用系统原来的INT 08H,否则将影响磁盘马达的关闭和系统的计时,另外,我们还主要依赖原来的INT 08H向中断控制器发中断结束指令(EOI);3, 线程的阻塞与唤醒线程的阻塞:主要是当某一线程需要阻塞的时候,将其插入阻塞队列中,等待唤醒进程唤醒,所以其过程为:首先,将线程的状态置为阻塞态,然后将线程插入指定的阻塞队列末尾,并重新进行CPU调度。线程的唤醒:主要是唤醒阻塞队列里面的线程,所以其过程是:把阻塞队列头上的第一个线程的TCB取下来,并将其状态改为就绪状态,等待CPU调度4, 线程的同步与互斥在这个系统中是采用记录型信号量机制来实现同步与互斥的,实现的方法:采用P ,V操作,设置两个信号量:一个为互斥信号量,一个为临界资源数目;5, 利用消息缓冲队列的线程间通信线程间的通信,关键采用send()与receive()来实现,通过发送一个文本信息来显示通信的过程,其过程为:send()函数:消息的发送者需要提供接收者的标识符,消息的长度以及消息正文的起始地址等信息,然后在发送原语里申请一空闲的消息缓冲区,用相应的信息来装配该消息缓冲区,并把它插入到接收者的消息队列中去。Receive()函数:消息的接受者必须给出发送者的标识符,接受区的起始地址等信息,然后从自己的消息队列中取得相应的发送者发送来的消息缓冲区,将消息正文复制到接受区中,并释放相应的消息缓冲区。五, 系统的详细过程#include #include #include #include #include #define NTCB 5 /*系统线程的最大数*/#define NTEXT 20 /*记录消息正文的长度*/#define NBUF 5 /*消息缓冲区的大小*/#define BUFLEN 5 /*缓冲池的大小*/#define FINISHED 0 /*终止*/#define RUNNING 1 /*执行*/#define READY 2 /*就绪*/#define BLOCKED 3 /*阻塞*/#define GET_INDOS 0x34#define GET_CRIT_ERR 0x5d06 char far *indos_ptr=0; /*该指针变量存放INDOS标志的地址*/char far *crit_err_ptr=0; /*该指针变量存放严重错误标志的地址*/static int now=0; /*全局变量定义当前线程*/int timecount = 0; /*计时用的*/int TL=1;int n = 0; /* 共享的临界资源 */long buf1BUFLEN; /* 存放整数的缓冲池*/int in = 0; /* 数进缓冲区时的缓冲区下标 */int out = 0; /* 数出缓冲区时的缓冲区下标 */struct buffer int sender; /* 消息发送者的内部标识 */ int size; /* 消息长度 next; return(buff); struct int_regs unsigned bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags,overip,overcs; *xp;typedef struct int value; struct TCB *wq; semaphore;semaphore enf = 2, NULL ;semaphore mutex = 1, NULL ;semaphore sfb= NBUF, NULL ;/* 空闲缓冲队列记数信号量buf */struct TCB int id; unsigned char *stack; /* 线程堆栈的起始地址 */ unsigned ss; /* 堆栈段址 */ unsigned sp; /* 堆栈指针 */ char state; /* 线程状态 ,取值可以是FINISHED、RUNNING、READY、BLOCKED*/ char name10; /* 线程的外部标识符 */ unsigned *chan; struct TCB *next; /* 链接字段 */ struct buffer *mq; /* 接收线程的消息队列队首指针 */ semaphore mutex; /* 接收线程的消息队列的互斥信号量 */ semaphore sm; /* 接收线程的消息队列的计数信号量,用于实现同步 */tcbNTCB; /*NTCB是系统允许的最多任务数*/typedef int (far *codeptr)(void); /*定义了一个函数指针类型*/int create(char *name,codeptr code,int stacklen);void destroy(int id);void over(void);void interrupt swtch();void print_state();void InitDos(void);int DosBusy(void);void interrupt (*old_int8)(void); /*定义一个函数指针old_int8*/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 InitTcb(void) int i; for (i = 1; i NTCB; i+) tcbi.stack = NULL; tcbi.state = FINISHED; tcbi.chan = NULL; 0 = 0; tcbi.next = NULL; tcbi.mq = NULL; tcbi.mutex.value = 1; tcbi.mutex.wq = NULL; tcbi.sm.value = 0; tcbi.sm.wq = NULL; void print_state() int i; for (i = 0; i NTCB; i+) printf(Thread%dstate is:, i); if (tcbi.state = FINISHED) printf(FINNISHED!n); else if (tcbi.state = RUNNING) printf(RUNNING!n); else if (tcbi.state = BLOCKED) printf(BLOCKED!n); else printf(READY!n); int create(char *name,codeptr code,int stacklen) int id=-1,i; for(i=0;ics = FP_SEG(code);/*段内偏移地址*/ xp-ip = FP_OFF(code); xp-ds = _DS;/*数据段段基址*/ xp-es = _DS;/*附加数据段段基址*/ xp-flags = 0x200; xp-overcs= FP_SEG(over); xp-overip= FP_OFF(over); tcbid.ss = FP_SEG(xp); tcbid.sp = FP_OFF(xp); tcbid.state = READY; for (i = 0; i 10; i+, name+) if (i = *name) = NULL) break; 9 = 0; enable(); printf(n* The new thread %d %s has been created successfully *n,id,); return id; ;void destroy(int id) disable(); free(tcbid.stack); tcbid.stack = NULL; tcbid.state = FINISHED; printf(n* The thread %s has been destroyed *n,); 0 = 0; enable();void over(void) destroy(now); swtch(); /* InitDos()函数:功能是获得INDOS标志的地址和严重错误标志的地址 */void InitDos(void) union REGS regs; struct SREGS segregs; /* 获得 INDOS 标志的地址 */ regs.h.ah=GET_INDOS; /* intdosx() :Turbo C的库函数,其功能是调用DOS的INT21H中断*/ intdosx(®s,®s,&segregs); /* MK_FP():不是一个函数,只是一个宏。*/*其功能是做段基址加上偏移地址的运算,也就是取实际地址。 */ indos_ptr=MK_FP(segregs.es,regs.x.bx); /*获得严重错误标志的地址 */ /*代码中用到的_osmajor、_osminor是Turbo C的全程变量,其中前者为*/*DOS版本号的主要部分,后者为版本号的次要部分。*/ if (_osmajor3) 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(®s,®s,&segregs); crit_err_ptr=MK_FP(segregs.ds,regs.x.si); /* DosBusy():函数功能是获得Indos标志及严重错误标志的值,判断是否dos忙:*/ /* 如果返回值是1,表示dos忙;*/ /* 如果返回值是0,表示dos不忙;*/ /* 如果返回值是-1,表示还没有调用InitDos() */int DosBusy(void) if (indos_ptr & crit_err_ptr) return(*indos_ptr | *crit_err_ptr); else return(-1); /* InitDos() hasnt been called */void interrupt new_int8(void) int loop=0; (*old_int8)(); if(+timecount TL) return; if(DosBusy() return; disable(); /*保存旧线程的指针*/ tcbnow.ss = _SS; tcbnow.sp = _SP; if(tcbnow.state = RUNNING) tcbnow.state = READY; if( +now = NTCB ) now = 1; while(tcbnow.state != READY & +loop NTCB-1) now+; if(now = NTCB) now = 1; if(tcbnow.state != READY) now = 0; _SS = tcbnow.ss; _SP = tcbnow.sp; tcbnow.state = RUNNING; timecount = 0; /* tcb_state();*/ enable();void interrupt swtch(void) int loop=0; disable(); tcbnow.ss=_SS; tcbnow.sp=_SP; if(tcbnow.state=RUNNING) tcbnow.state=READY;/* 放入就绪队列中 */ if(+now=NTCB) now=0; while(tcbnow.state!=READY & loop+next != NULL) tcbp = tcbp-next; tcbp-next = &tcbid; tcbid.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-valuewq); block(unsigned *)sem,qp); printf(n*i dont have semaphore so hang-up*n); enable(); void v(semaphore *sem) struct TCB *qp; disable(); qp=&(sem-wq); sem-value=sem-value+1; if(sem-valuesender != sende) & (p-next != NULL) q = p; p = p-next; if (p-sender = sende) 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,id=-1; disable(); for(i=0;isender=now; buff-size=size; buff-next=NULL; for(i=0;isize;i+,a+) buff-texti=*a; /*将消息缓冲区插入到接收者线程的消息队列末尾*/ p(&tcbid.mutex); insert(&(tcbid.mq),buff); v(&tcbid.mutex); v(&tcbid.sm); enable(); printf(send successfully,the massage );void init_buf(void) int i; for (i = 0; i NBUF - 1; i+) bufi.next = &bufi + 1; bufi.next = NULL; freebuf = &buf0;int receive(char *sender, char *b) int i, size, id = -1; struct buffer *buff; disable(); for (i = 0; i size; for (i = 0; i size; i+, b+) *b = buff-texti; p(&mutex); insert(&freebuf, buff); v(&mutex); v(&sfb); enable(); return (size);void free_all(void) int i; for (i = 1; i NTCB; i+) if (tcbi.stack) 0 = 0; tcbi.state = FINISHED; free(tcbi.stack); tcbi.stack = NULL; void f1(void) int i,j,k; for(i=0;i60;i+) putchar(a); /*延时*/ for(j=0;j10000;j+) for(k=0;k10000;k+); void f2(void) int i,j,k; for(i=0;i30;i+) putchar(b); /*延时*/ for(j=0;j10000;j+) for(k=0;k10000;k+); void f3(void) int i,j,k; for(i=0;i60;i+) p(&mutex); putchar(a); /*延时*/ for(j=0;j1000;j+) for(k=0;k1000;k+); putchar(a); v(&mutex); void f4(void) int i,j,k; for(i=0;i30;i+) p(&mutex); putchar(b); /*延时*/ for(j=0;j1000;j+) for(k=0;k1000;k+); putchar(b); v(&mutex); void sender(void) int i, j,n; char a10; loop: for (i = 0; i 10; i+) strcpy(a, message); a7 = 0+n ; a8 = 0; send(receiver, a, strlen(a); printf(sender:Message %s has been sentn, 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, j, size; char b10; for (i = 0; i 10; i+) b0 = 0; while (size = receive(sender, b) = -1) ; printf(receiver: Message is received-);/* 已接收到消息 */ for (j = 0; j size; j+) putchar(bj); printf(n); strcpy(b, ok); send(sender, b, 3);/* 发送确认消息 */void main() int select=-1; InitDos(); InitTcb(); old_int8 = getvect(8); strcpy(, main); tcb0.state = RUNNING; now = 0; for (; select;) do clrscr(); printf( _n); printf(|* Operating system *|n); printf(|_|n);printf(| 1.fcfs |n);printf(| 2.Round robin |n); printf(| 3.share critical resource(in mutual exclusion) |n);printf(| 4.send and receive massage |n); printf(nt Please enter the function num.(1-4):); scanf(%d, &select); while (select 4); switch (select) case 1: print_state(); create(f1, (codeptr) f1, 1024); print_state(); getch(); create(f2, (codeptr) f2, 1024); print_state(); getch(); clrscr(); printf(t No deprivation in two threads concurrent running: n); /*不剥夺方式下两个线程的并发执行*/ printf(t Thread f1 continuous output a 60 times,n); /*其中线程f1不断输出字母a,共60次*/ printf(t Thread f2 continuous output b 30 times.n); /*而线程f2不断输出字母b,共30次*/ printf(t Press any key to continue!n); /*按任意键继续*/ getch(); print_state(); swtch(); print_state(); getch(); free_all(); getch(); break; case 2: print_state(); create(f1, (codeptr) f1, 1024); print_state(); getch(); create(f2, (codeptr) f2, 1024); print_state(); getch(); clrscr(); printf(t Round-Robin in two threads concurrent running:n); /*时间片轮转方式下两个线程的并发执行*/ printf(t Thread f1 continuous output a 60 times, n); /*其中线程f1不断输出字母a,共60次*/ printf(t Threa
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 数控技术应用试题及答案
- 2025年北京个人房屋租赁合同范本官方版下载
- 2025官方版股权投资合同范本
- 2025年高二【数学(人教A版)】两条平行直线间的距离公式-学习任务单
- 2025抵质押物的借款合同范本
- 公园养护基本知识培训总结
- 公司职工财务知识培训课件
- 高职卫生专业招生面试题库
- 2025关于汽车租赁的合同样本
- 市场调研与创意策划的关系面试题及答案解析
- 2025年景泰蓝工艺瓶行业深度研究报告
- 呼出气一氧化氮检测流程及临床应用的专家共识(2025版)解读课件
- 场景理论的内容框架及应对策略研究
- 《血液肿瘤免疫及靶向药物治疗相关性感染预防及诊治中国专家共识(2025年版)》解读
- 标准厂房混凝土预制构件施工现场的环境保护措施
- 电缆井及过轨管施工技术交底1
- 苏豪控股集团招聘笔试题库2025
- 肿瘤标志物临床应用试题及答案
- 高校辅导员考试全面解析试题及答案
- 超星尔雅学习通《脑洞大开背后的创新思维(大连理工大学)》2025章节测试答案
- 护理服务规范与礼仪标准:护理服务规范礼仪标准及考核评分标准
评论
0/150
提交评论