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