本来想从网上随便找段代码应付一下老师,没想到百度的代码都是不完全(原因是老师验收太松了),只能自力更生,将他修补完全.只写了部分注解,后来实在写不动了,可以参考指导书, 以后有空再加上去。
一共演示了两个例子,一个利用pv操作实现读者写者问题,还有一个是线程通信。
用的编译器是TC,就是实验室的,用其他编译器会报错。运行一段时间会停止,按任意键即可继续运行。
#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 0x5d06 char 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(®s,®s,&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(®s,®s,&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