操作系统实验2-互斥与同步
来源:互联网 发布:聚翔网络 编辑:程序博客网 时间:2024/05/01 08:37
实验分两部分,第一部分,实现互斥
思路很简单,利用信号量,将其值初始化为1,semaphore resource = {1,NULL};
获取资源时做P()操作,释放资源使用权时做V()操作。
所以
void p1( ){ long i, j, k; p(&semlock); //获取资源使用权,如果不能获取,会被放到信号量队列中等待资源可用被唤醒 //中间过程相当于是在使用这个资源(模拟) for(i=0; i<40; i++) { putchar('a'); for(j=0; j<1000; j++) for(k=0; k<20000; k++); } v(&semlock); //释放资源,信号量值加1,队列中第一个线程会被唤醒(如果队列不为空)}void p2( ){ long i, j, k; p(&semlock); //同p1() for(i=0; i<20; i++) { putchar('b'); for(j=0; j<1000; j++) for(k=0; k<20000; k++); } v(&semlock);}另外,我们要更改Find()调度程序,找到没有被阻塞的线程来调度
int Find(){ int i,j; for(i = 1; i < NTCB; i++) { if(tcb[i].state != FINISHED && tcb[i].state != BLOCKED) return i; } return 0;}到这里,互斥锁就完成了。上最终代码:
#include <stdlib.h>#include <dos.h>#include <stdio.h>#define GET_INDOS 0x34 /* 34H 系统功能调用 */#define GET_CRIT_ERR 0x5d06 /* 5D06H号系统功能调用 */#define BLANK -1#define FINISHED 0 /* 终止 */#define RUNNING 1 /* 执行 */#define READY 2 /* 就绪 */#define BLOCKED 3 /* 阻塞 */#define NTCB 3 /* 系统线程的最大数 */#define TL 10 /* 时间片大小 */#define NBUF 10 /* 消息缓冲区数目 */#define NTEXT 50 /* 文本输出大小 */char far* intdos_ptr=0;char far* crit_err_ptr=0;int timecount=0;int current=-1;typedef unsigned int UINT16;typedef struct/* 信号量 */{ int value; struct TCB* wq;} semaphore;int critical = 0; //semaphore semlock = {1,NULL};struct TCB /* 线程控制块 */{ unsigned char* stack; /* 堆栈的起始地址 */ unsigned ss; unsigned sp; /* 堆栈段址和堆栈指针 */ char state; /* 进程状态 */ char name[10]; /* 线程的外部标识符 */ int value; /*优先级*/ struct TCB* next; /* 指向控制快指针 */ semaphore mutex; /* 互斥信号量 */} tcb[NTCB];struct int_regs /* 堆栈现场保护和恢复结构体 */{ unsigned BP,DI,SI,DS,ES,DX,CX,BX,AX,IP,CS,Flags,off,seg;};typedef int(far* codeptr)(void);void interrupt(*old_int8)(void);int DosBusy(void);void InitIndos(void);void InitTcb();void interrupt new_int8(void);void interrupt swtch();void p(semaphore *sem);void v(semaphore *sem);int Create(char* name,codeptr code,int stacklen,int prio); /* 创建线程 */void Destroy(int i);void p1( ){ long i, j, k; p(&semlock); for(i=0; i<40; i++) { putchar('a'); for(j=0; j<1000; j++) for(k=0; k<20000; k++); } v(&semlock);}void p2( ){ long i, j, k; p(&semlock); for(i=0; i<20; i++) { putchar('b'); for(j=0; j<1000; j++) for(k=0; k<20000; k++); } v(&semlock);}void InitInDos() /* 取得INDOS标志和严重错误标志地址 */{ union REGS regs; struct SREGS segregs; regs.h.ah=GET_INDOS; /* 使用34H号系统功能调用 */ intdosx(®s,®s,&segregs); intdos_ptr=MK_FP(segregs.es,regs.x.bx); if(_osmajor<3) crit_err_ptr=intdos_ptr+1; /* 严重错误在INDOS后一字节处 */ else if(_osmajor==3&&_osminor==0) crit_err_ptr=intdos_ptr-1; /* 严重错误在INDOS前一字节处 */ else { regs.x.ax=GET_CRIT_ERR; intdosx(®s,®s,&segregs); crit_err_ptr=MK_FP(segregs.ds,regs.x.si); }}int DosBusy(void) /* 判断DOS是否忙 */{ if(intdos_ptr&&crit_err_ptr) return(*intdos_ptr||*crit_err_ptr); /* DOS忙,返回严重错误标志 */ else return(-1); /* DOS不忙 */}void InitTcb() /* 初始化线程 */{ int i; for(i=0; i<NTCB; i++) { tcb[i].state=BLANK; /* 初始状态标志 */ tcb[i].mutex.value=1; tcb[i].mutex.wq=NULL; }}void Destroy(int i){ if(tcb[i].state==RUNNING) { disable(); tcb[i].state=FINISHED; strcpy(tcb[i].name,NULL); free(tcb[i].stack); tcb[i].ss=0; tcb[i].sp=0; enable(); }// return;}void over(){ Destroy(current); swtch();}int Create(char *name,codeptr code,int stacklen,int value){ int i; char *p; struct int_regs *pt; unsigned int *pp; for(i=1; i<NTCB; i++) { if(tcb[i].state==BLANK||tcb[i].state==FINISHED) break; } if(i==NTCB) return-1; tcb[i].value=value; strcpy(tcb[i].name,name); tcb[i].stack=(p=(unsigned char*)malloc(stacklen)); memset(tcb[i].stack, 0xff, stacklen); p=p+stacklen; pt=(struct int_regs*)p; pt--; pt->Flags=0x200; pt->CS=FP_SEG(code); pt->IP=FP_OFF(code); pt->off=FP_OFF(over); pt->seg=FP_SEG(over); pt->DS=_DS; pt->ES=_ES; tcb[i].sp=FP_OFF(pt); tcb[i].ss=FP_SEG(pt); tcb[i].state=READY; return i;}void tcb_state() /* 线程状态信息 */{ int i; for(i=0; i<NTCB; i++) if(tcb[i].state!=BLANK) { switch(tcb[i].state) { case FINISHED: printf("\ntcb[%d] is FINISHED\n",i); break; case RUNNING: printf("tcb[%d] is RUNNING\n",i); break; case READY: printf("tcb[%d] is READY\n",i); break; case BLOCKED: printf("tcb[%d] is BLOCKED\n",i); break; } }}int all_finished(){ int i; for(i=1; i<NTCB; i++) if(tcb[i].state==RUNNING||tcb[i].state==BLOCKED||tcb[i].state==READY) return 0; return 1;}int Find(){ int i,j; for(i = 1; i < NTCB; i++) { if(tcb[i].state != FINISHED && tcb[i].state != BLOCKED) return i; } return 0;}void interrupt new_int8(void) /* CPU 调度*/{ int i; (*old_int8)(); /* 指向原来时钟中断处理过程入口的中断处理函数指针 */ timecount++; if(timecount==TL) /* 时间片是否到? */ { if(!DosBusy()) /* DOS是否忙? */ { disable(); tcb[current].ss=_SS; /* 保存现场 */ tcb[current].sp=_SP; if(tcb[current].state==RUNNING) tcb[current].state=READY; i=Find(); if(i<0) return; _SS=tcb[i].ss; _SP=tcb[i].sp; tcb[i].state=RUNNING; current=i; timecount=0; /* 重新计时 */ enable(); } else return; } else return;}void interrupt swtch() /* 其他原因CPU调度 */{ int i; if(tcb[current].state!=FINISHED &¤t!=0&&tcb[current].state!=BLOCKED) /* 当前线程还没结束 */ return; i=Find(); if(i<0) return; disable(); tcb[current].ss=_SS; tcb[current].sp=_SP; if(tcb[current].state==RUNNING) tcb[current].state=READY; /* 放入就绪队列中 */ _SS=tcb[i].ss; _SP=tcb[i].sp; /* 保存现场 */ tcb[i].state=RUNNING; current=i; enable();}void block(struct TCB **p) /* 阻塞原语 */{ struct TCB *pp; tcb[current].state=BLOCKED; if((*p)==NULL) *p=&tcb[current]; /* 阻塞队列空,直接放入 */ else { pp=*p; while(pp->next) pp=pp->next; /* 找到阻塞队列最后一个节点 */ pp->next=&tcb[current]; /* 放入阻塞队列 */ } tcb[current].next=NULL; swtch(); /* 重新进行CPU调度 */}void wakeup_first(struct TCB **p) /* 唤醒队首线程 */{ struct TCB *pl; if((*p)==NULL) return; pl=(*p); (*p)=(*p)->next; /* 得到阻塞队列队首线程 */ pl->state=READY; /* 修为就绪状态 */ pl->next=NULL;}void p(semaphore *sem){ struct TCB **qp; disable(); sem->value=sem->value-1; 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; if(sem->value>=0) wakeup_first(qp); enable();}void main(){ long i, j, k; InitInDos(); InitTcb(); old_int8=getvect(8); strcpy(tcb[0].name,"main"); tcb[0].state=RUNNING; tcb[0].value=0; current=0; Create("p1",(codeptr)p1,1024,5); Create("p2",(codeptr)p2,1024,5); disable(); setvect(8, new_int8); enable(); while(!all_finished()); { } tcb[0].name[0]='\0'; tcb[0].state=FINISHED; setvect(8,old_int8); tcb_state(); printf("\n Muli_task system teminated \n");}
第二部分,同步问题,我们用最经典的生产者消费者来说明。
首先,定义临界资源访问信号里:semaphore resource = {0,NULL};,注意,值初始化为0;
接下来,生产者与消费者代码实现:
void p1( ) // 生产者{ long i, j, k; for(i=0; i<40; i++) { putchar('a'); for(j=0; j<1000; j++) for(k=0; k<20000; k++); } // 前面的过程就是生产者一直在生产的过程,现在生产完成了,v操作通知消费者消费咯 v(&resource);}void p2( ) //消费者{ long i, j, k; p(&resource); //看看有没有可用的资源来消费,若没有,则被放到信号里resource的队列中,直至资源可用被唤醒 // 下面就是消费者消费过程(模拟,别当真) for(i=0; i<20; i++) { putchar('b'); for(j=0; j<1000; j++) for(k=0; k<20000; k++); }}好,上最终代码:
#include <stdlib.h>#include <dos.h>#include <stdio.h>#define GET_INDOS 0x34 /* 34H 系统功能调用 */#define GET_CRIT_ERR 0x5d06 /* 5D06H号系统功能调用 */#define BLANK -1#define FINISHED 0 /* 终止 */#define RUNNING 1 /* 执行 */#define READY 2 /* 就绪 */#define BLOCKED 3 /* 阻塞 */#define NTCB 3 /* 系统线程的最大数 */#define TL 10 /* 时间片大小 */#define NBUF 10 /* 消息缓冲区数目 */#define NTEXT 50 /* 文本输出大小 */char far* intdos_ptr=0;char far* crit_err_ptr=0;int timecount=0;int current=-1;typedef unsigned int UINT16;typedef struct/* 信号量 */{ int value; struct TCB* wq;} semaphore;semaphore resource = {0,NULL}; //struct TCB /* 线程控制块 */{ unsigned char* stack; /* 堆栈的起始地址 */ unsigned ss; unsigned sp; /* 堆栈段址和堆栈指针 */ char state; /* 进程状态 */ char name[10]; /* 线程的外部标识符 */ int value; /*优先级*/ struct TCB* next; /* 指向控制快指针 */ semaphore mutex; /* 互斥信号量 */} tcb[NTCB];struct int_regs /* 堆栈现场保护和恢复结构体 */{ unsigned BP,DI,SI,DS,ES,DX,CX,BX,AX,IP,CS,Flags,off,seg;};typedef int(far* codeptr)(void);void interrupt(*old_int8)(void);int DosBusy(void);void InitIndos(void);void InitTcb();void interrupt new_int8(void);void interrupt swtch();void p(semaphore *sem);void v(semaphore *sem);int Create(char* name,codeptr code,int stacklen,int prio); /* 创建线程 */void Destroy(int i);void p1( ) // 生产者{ long i, j, k; for(i=0; i<40; i++) { putchar('a'); for(j=0; j<1000; j++) for(k=0; k<20000; k++); } v(&resource);}void p2( ) //消费者{ long i, j, k; p(&resource); for(i=0; i<20; i++) { putchar('b'); for(j=0; j<1000; j++) for(k=0; k<20000; k++); }}void InitInDos() /* 取得INDOS标志和严重错误标志地址 */{ union REGS regs; struct SREGS segregs; regs.h.ah=GET_INDOS; /* 使用34H号系统功能调用 */ intdosx(®s,®s,&segregs); intdos_ptr=MK_FP(segregs.es,regs.x.bx); if(_osmajor<3) crit_err_ptr=intdos_ptr+1; /* 严重错误在INDOS后一字节处 */ else if(_osmajor==3&&_osminor==0) crit_err_ptr=intdos_ptr-1; /* 严重错误在INDOS前一字节处 */ else { regs.x.ax=GET_CRIT_ERR; intdosx(®s,®s,&segregs); crit_err_ptr=MK_FP(segregs.ds,regs.x.si); }}int DosBusy(void) /* 判断DOS是否忙 */{ if(intdos_ptr&&crit_err_ptr) return(*intdos_ptr||*crit_err_ptr); /* DOS忙,返回严重错误标志 */ else return(-1); /* DOS不忙 */}void InitTcb() /* 初始化线程 */{ int i; for(i=0; i<NTCB; i++) { tcb[i].state=BLANK; /* 初始状态标志 */ tcb[i].mutex.value=1; tcb[i].mutex.wq=NULL; }}void Destroy(int i){ if(tcb[i].state==RUNNING) { disable(); tcb[i].state=FINISHED; strcpy(tcb[i].name,NULL); free(tcb[i].stack); tcb[i].ss=0; tcb[i].sp=0; enable(); }// return;}void over(){ Destroy(current); swtch();}int Create(char *name,codeptr code,int stacklen,int value){ int i; char *p; struct int_regs *pt; unsigned int *pp; for(i=1; i<NTCB; i++) { if(tcb[i].state==BLANK||tcb[i].state==FINISHED) break; } if(i==NTCB) return-1; tcb[i].value=value; strcpy(tcb[i].name,name); tcb[i].stack=(p=(unsigned char*)malloc(stacklen)); memset(tcb[i].stack, 0xff, stacklen); p=p+stacklen; pt=(struct int_regs*)p; pt--; pt->Flags=0x200; pt->CS=FP_SEG(code); pt->IP=FP_OFF(code); pt->off=FP_OFF(over); pt->seg=FP_SEG(over); pt->DS=_DS; pt->ES=_ES; tcb[i].sp=FP_OFF(pt); tcb[i].ss=FP_SEG(pt); tcb[i].state=READY; return i;}void tcb_state() /* 线程状态信息 */{ int i; for(i=0; i<NTCB; i++) if(tcb[i].state!=BLANK) { switch(tcb[i].state) { case FINISHED: printf("\ntcb[%d] is FINISHED\n",i); break; case RUNNING: printf("tcb[%d] is RUNNING\n",i); break; case READY: printf("tcb[%d] is READY\n",i); break; case BLOCKED: printf("tcb[%d] is BLOCKED\n",i); break; } }}int all_finished(){ int i; for(i=1; i<NTCB; i++) if(tcb[i].state==RUNNING||tcb[i].state==BLOCKED||tcb[i].state==READY) return 0; return 1;}int Find(){ int i,j; i=current; while(tcb[i=((i+1)%NTCB)].state!=READY ||i==current); return i;}/*int Find(){ int i,index,max_pri; i = index = max_pri = 0; for( ; i < NTCB; i++) { if(tcb[i].state != FINISHED && tcb[i].state != BLOCKED && tcb[i].value > max_pri) { index = i; max_pri = tcb[i].value; } } return index;}*/void interrupt new_int8(void) /* CPU 调度*/{ int i; (*old_int8)(); /* 指向原来时钟中断处理过程入口的中断处理函数指针 */ timecount++; if(timecount==TL) /* 时间片是否到? */ { if(!DosBusy()) /* DOS是否忙? */ { disable(); tcb[current].ss=_SS; /* 保存现场 */ tcb[current].sp=_SP; if(tcb[current].state==RUNNING) tcb[current].state=READY; i=Find(); if(i<0) return; _SS=tcb[i].ss; _SP=tcb[i].sp; tcb[i].state=RUNNING; current=i; timecount=0; /* 重新计时 */ enable(); } else return; } else return;}void interrupt swtch() /* 其他原因CPU调度 */{ int i; if(tcb[current].state!=FINISHED &¤t!=0&&tcb[current].state!=BLOCKED) /* 当前线程还没结束 */ return; i=Find(); if(i<0) return; disable(); tcb[current].ss=_SS; tcb[current].sp=_SP; if(tcb[current].state==RUNNING) tcb[current].state=READY; /* 放入就绪队列中 */ _SS=tcb[i].ss; _SP=tcb[i].sp; /* 保存现场 */ tcb[i].state=RUNNING; current=i; enable();}void block(struct TCB **p) /* 阻塞原语 */{ struct TCB *pp; tcb[current].state=BLOCKED; if((*p)==NULL) *p=&tcb[current]; /* 阻塞队列空,直接放入 */ else { pp=*p; while(pp->next) pp=pp->next; /* 找到阻塞队列最后一个节点 */ pp->next=&tcb[current]; /* 放入阻塞队列 */ } tcb[current].next=NULL; swtch(); /* 重新进行CPU调度 */}void wakeup_first(struct TCB **p) /* 唤醒队首线程 */{ struct TCB *pl; if((*p)==NULL) return; pl=(*p); (*p)=(*p)->next; /* 得到阻塞队列队首线程 */ pl->state=READY; /* 修为就绪状态 */ pl->next=NULL;}void p(semaphore *sem){ struct TCB **qp; disable(); sem->value=sem->value-1; 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; if(sem->value>=0) wakeup_first(qp); enable();}void main(){ long i, j, k; InitInDos(); InitTcb(); old_int8=getvect(8); strcpy(tcb[0].name,"main"); tcb[0].state=RUNNING; tcb[0].value=0; current=0; Create("p1",(codeptr)p1,1024,5); Create("p2",(codeptr)p2,1024,5); disable(); setvect(8, new_int8); enable(); while(!all_finished()); { } tcb[0].name[0]='\0'; tcb[0].state=FINISHED; setvect(8,old_int8); tcb_state(); printf("\n Muli_task system teminated \n");}
好了,打完收工。
0 0
- 操作系统实验2-互斥与同步
- 操作系统实验--同步互斥
- 【操作系统】互斥与同步
- 操作系统 进程/线程 同步与互斥
- 操作系统的互斥与同步
- 操作系统之同步与互斥
- 操作系统中的互斥,同步与死锁
- 操作系统--同步与互斥问题
- 操作系统--进程的互斥与同步
- 操作系统进程--互斥实验
- 操作系统学习笔记——进程互斥与同步
- 操作系统-并发性:互斥与同步-复习 & 练习题
- 【操作系统笔记】同步与互斥的区别和联系
- linux操作系统之互斥与同步区别
- 操作系统课程设计-线程和进程的同步与互斥
- 操作系统之进程互斥与同步和线程
- 操作系统概论(3) --进程的同步与互斥
- 2013-10-24 实验之信号量同步与互斥
- 03 继承 初始化方法 便利构造器
- POJ1274匈牙利算法DFS实现
- poj 2516 最小费用最大流
- C# 关于控件的z-order(Z轴次序)属性(By dlm)
- Lua中的操作系统库
- 操作系统实验2-互斥与同步
- 犀牛——第19章 JQuery类库 19.4使用jQuery处理事件
- Socket笔记
- 使用别人webService简介
- 树与二叉树
- Mac笔记( 二) Mac OS X 10.10 安装与配置PhoneGap
- 二叉树与森林的转换
- Js判断键盘按键
- 解决问题:“System Program Problem Detected” Messages From Ubuntu