本來想從網上隨便找段代碼應付一下老師,沒想到百度的代碼都是不完全(原因是老師驗收太鬆了),只能自力更生,將他修補完全.只寫了部分註解,後來實在寫不動了,可以參考指導書, 以後有空再加上去。
一共演示了兩個例子,一個利用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