消息缓冲队列通信机制其基本思想是根据“生产者——消费者”原理,利用内存中公用消息缓冲区实现进程间的信息交换。
在这种通信机制中,首先需要在内存中开辟若干空闲消息缓冲区,用以存放要通信的消息。每当一个进程需要向另一个进程发送消息时,便向系统申请一个空闲消息缓冲区,并把已准备好的消息复制到该缓冲区,然后把该消息缓冲区插入到接收进程的消息队列中,最后通知接收进程。接收进程接收到发送进程发来的通知后,从本进程的消息队列中摘下一消息缓冲区,取出其中的信息,然后把消息缓冲区作为空闲消息缓冲区归还给系统。系统负责管理公用消息缓冲区以及消息的传递。
1 // 消息缓冲队列 2 // 2016.1.7 3 4 #include <stdlib.h> 5 #include <dos.h> 6 #include <stdio.h> 7 8 #define GET_INDOS 0x34 /* 34H 系统功能调用 */ 9 #define GET_CRIT_ERR 0x5d06 /* 5D06H号系统功能调用 */ 10 11 #define BLANK -1 12 #define FINISHED 0 /* 终止 */ 13 #define RUNNING 1 /* 执行 */ 14 #define READY 2 /* 就绪 */ 15 #define BLOCKED 3 /* 阻塞 */ 16 #define NTCB 3 /* 系统线程的最大数 */ 17 18 #define TL 10 /* 时间片大小 */ 19 #define NBUF 2 /* 消息缓冲区数目 */ 20 #define NTEXT 50 /* 文本输出大小 */ 21 22 23 char far* intdos_ptr=0; 24 char far* crit_err_ptr=0; 25 int timecount=0; 26 int current=-1; 27 28 typedef unsigned int UINT16; 29 30 typedef struct/* 信号量 */ 31 { 32 int value; 33 struct TCB* wq; 34 }semaphore; 35 36 semaphore mutexfb={1,NULL}; // freebuf 互斥变量 初值 1 37 semaphore sfb={2,NULL}; // 计数信号量 38 semaphore bufferSem1, bufferSem2; 39 40 // 消息缓冲区 41 // 空闲缓冲队列 freebuf(临界资源) 42 struct buffer 43 { 44 int sender; /*消息发送者的标识数 */ 45 int size; /* 消息长度<=NTEXT 个字节 */ 46 char text[NTEXT]; /* 消息正文 */ 47 struct buffer* next; /* 指向下一个消息缓冲区的指针 */ 48 } *freebuf; 49 50 /* 线程控制块 */ 51 struct TCB 52 { 53 unsigned char* stack; /* 堆栈的起始地址 */ 54 unsigned ss; 55 unsigned sp; /* 堆栈段址和堆栈指针 */ 56 char state; /* 进程状态 */ 57 char name[10]; /* 线程的外部标识符 */ 58 int value; /*优先级*/ 59 struct TCB* next; /* 指向控制快指针 */ 60 struct buffer* mq; /* 消息缓冲队列首指针 */ 61 semaphore mutex; /* 互斥信号量 */ 62 semaphore sm; /* 消息缓冲队列计数信号量*/ 63 }tcb[NTCB]; 64 65 /* 堆栈现场保护和恢复结构体 */ 66 struct int_regs 67 { 68 unsigned BP,DI,SI,DS,ES,DX,CX,BX,AX,IP,CS,Flags,off,seg; 69 }; 70 71 typedef int(far* codeptr)(void); 72 void interrupt(*old_int8)(void); 73 int DosBusy(void); 74 void InitIndos(void); 75 void InitTcb(); 76 void interrupt new_int8(void); 77 void interrupt swtch(); 78 void send(char *receiver,char *a,int size); 79 int receive(char *sender,char *a); 80 void p(semaphore *sem); 81 void v(semaphore *sem); 82 int Create(char* name,codeptr code,int stacklen,int prio); /* 创建线程 */ 83 void Destroy(int i); 84 85 86 // 1#线程 87 void f1() 88 { 89 90 while(1) 91 { 92 p(&bufferSem1); 93 94 send("f2","f1 send message to f2",NTEXT); 95 96 printf("f1 sending! "); 97 98 v(&bufferSem2); 99 } 100 } 101 102 // 2#线程 103 void f2() 104 { 105 char a[NTEXT]; 106 107 while(1) 108 { 109 p(&bufferSem2); 110 111 receive("f1",a); 112 113 printf("f2 receiving! "); 114 115 v(&bufferSem1); 116 } 117 } 118 119 120 void InitInDos() /* 取得INDOS标志和严重错误标志地址 */ 121 { 122 union REGS regs; 123 struct SREGS segregs; 124 125 regs.h.ah=GET_INDOS; /* 使用34H号系统功能调用 */ 126 intdosx(®s,®s,&segregs); 127 128 intdos_ptr=MK_FP(segregs.es,regs.x.bx); 129 if(_osmajor<3) 130 crit_err_ptr=intdos_ptr+1; /* 严重错误在INDOS后一字节处 */ 131 else if(_osmajor==3&&_osminor==0) 132 crit_err_ptr=intdos_ptr-1; /* 严重错误在INDOS前一字节处 */ 133 else 134 { 135 regs.x.ax=GET_CRIT_ERR; 136 intdosx(®s,®s,&segregs); 137 crit_err_ptr=MK_FP(segregs.ds,regs.x.si); 138 } 139 } 140 141 int DosBusy(void) /* 判断DOS是否忙 */ 142 { 143 if(intdos_ptr&&crit_err_ptr) 144 return(*intdos_ptr||*crit_err_ptr); /* DOS忙,返回严重错误标志 */ 145 else 146 return(-1); /* DOS不忙 */ 147 } 148 149 void InitTcb() /* 初始化线程 */ 150 { 151 int i; 152 153 for(i=0;i<NTCB;i++) 154 { 155 tcb[i].state=BLANK; /* 初始状态标志 */ 156 tcb[i].mq=NULL; 157 tcb[i].mutex.value=1; 158 tcb[i].mutex.wq=NULL; 159 tcb[i].sm.value=0; 160 tcb[i].sm.wq=NULL; 161 } 162 } 163 164 void Destroy(int i) 165 { 166 167 if(tcb[i].state==RUNNING) 168 { 169 disable(); 170 tcb[i].state=FINISHED; 171 strcpy(tcb[i].name,NULL); 172 free(tcb[i].stack); 173 tcb[i].ss=0; 174 tcb[i].sp=0; 175 enable(); 176 } 177 178 } 179 180 void over() 181 { 182 Destroy(current); 183 swtch(); 184 } 185 186 int Create(char *name,codeptr code,int stacklen,int value) 187 { 188 int i; 189 char *p; 190 struct int_regs *pt; 191 unsigned int *pp; 192 193 for(i=1;i<NTCB;i++) 194 { 195 if(tcb[i].state==BLANK||tcb[i].state==FINISHED) 196 break; 197 } 198 if(i==NTCB) 199 return-1; 200 201 tcb[i].value=value; 202 strcpy(tcb[i].name,name); 203 tcb[i].stack=(p=(unsigned char*)malloc(stacklen)); 204 memset(tcb[i].stack, 0xff, stacklen); 205 p=p+stacklen; 206 207 #if 0 208 pt=(struct int_regs*)p; 209 pt--; 210 pt->Flags=0x200; 211 pt->CS=FP_SEG(code); 212 pt->IP=FP_OFF(code); 213 214 pt->off=FP_OFF(over); 215 pt->seg=FP_SEG(over); 216 pt->DS=_DS; 217 pt->ES=_ES; 218 tcb[i].sp=FP_OFF(pt); 219 tcb[i].ss=FP_SEG(pt); 220 #else if 221 /* 222 pp=(UINT16 *)(p-2); 223 *(pp)=FP_SEG(over); 224 *(pp-1)=FP_OFF(over); 225 *(pp-2)=0x200; 226 *(pp-3)=FP_SEG(code); 227 *(pp-4)=FP_OFF(code); 228 229 *(pp-9)=_ES; 230 *(pp-10)=_DS; 231 tcb[i].sp=FP_OFF(pp-13); 232 tcb[i].ss=FP_SEG(pp-13); 233 */ 234 235 *(p-1)=(FP_SEG(over)&0xff00)>>8; 236 *(p-2)=FP_SEG(over)&0x00ff; 237 238 *(p-3)=(FP_OFF(over)&0xff00)>>8; 239 *(p-4)=FP_OFF(over)&0x00ff; 240 241 *(p-5)=0x02; 242 *(p-6)=0x00; 243 244 *(p-7)=(FP_SEG(code)&0xff00)>>8; 245 *(p-8)=FP_SEG(code)&0x00ff; 246 247 *(p-9)=(FP_OFF(code)&0xff00)>>8; 248 *(p-10)=FP_OFF(code)&0x00ff; 249 250 *(p-19)=(_ES&0xff00)>>8; 251 *(p-20)=_ES&0x00ff; 252 253 *(p-21)=(_DS&0xff00)>>8; 254 *(p-22)=_DS&0x00ff; 255 256 tcb[i].sp=FP_OFF((UINT16 *)(p-28)); 257 tcb[i].ss=FP_SEG((UINT16 *)(p-28)); 258 259 #endif 260 261 tcb[i].state=READY; 262 263 return i; 264 } 265 266 void tcb_state() /* 线程状态信息 */ 267 { 268 int i; 269 270 for(i=0;i<NTCB;i++) 271 if(tcb[i].state!=BLANK) 272 { 273 switch(tcb[i].state) 274 { 275 case FINISHED: 276 printf(" tcb[%d] is FINISHED ",i); 277 break; 278 279 case RUNNING: 280 printf("tcb[%d] is RUNNING ",i); 281 break; 282 case READY: 283 printf("tcb[%d] is READY ",i); 284 break; 285 case BLOCKED: 286 printf("tcb[%d] is BLOCKED ",i); 287 288 break; 289 } 290 } 291 } 292 293 int all_finished() 294 { 295 int i; 296 297 for(i=1;i<NTCB;i++) 298 if(tcb[i].state==RUNNING||tcb[i].state==BLOCKED||tcb[i].state==READY) 299 return 0; 300 301 return 1; 302 } 303 304 int Find() 305 { 306 int i,j; 307 i=current; 308 309 while(tcb[i=((i+1)%NTCB)].state!=READY||i==current); 310 311 return i; 312 } 313 314 void interrupt new_int8(void) /* CPU 调度*/ 315 { 316 int i; 317 318 (*old_int8)(); /* 指向原来时钟中断处理过程入口的中断处理函数指针 */ 319 timecount++; 320 321 if(timecount==TL) /* 时间片是否到? */ 322 { 323 if(!DosBusy()) /* DOS是否忙? */ 324 { 325 disable(); 326 327 tcb[current].ss=_SS; /* 保存现场 */ 328 tcb[current].sp=_SP; 329 330 if(tcb[current].state==RUNNING) 331 tcb[current].state=READY; 332 333 i=Find(); 334 if(i<0) 335 return; 336 337 _SS=tcb[i].ss; 338 _SP=tcb[i].sp; 339 tcb[i].state=RUNNING; 340 current=i; 341 timecount=0; /* 重新计时 */ 342 343 enable(); 344 } 345 else 346 return; 347 } 348 else 349 return; 350 } 351 352 void interrupt swtch() /* 其他原因CPU调度 */ 353 { 354 int i; 355 356 if(tcb[current].state!=FINISHED 357 &¤t!=0&&tcb[current].state!=BLOCKED) /* 当前线程还没结束 */ 358 return; 359 360 i=Find(); 361 if(i<0) 362 return; 363 364 disable(); 365 tcb[current].ss=_SS; 366 tcb[current].sp=_SP; 367 368 if(tcb[current].state==RUNNING) 369 tcb[current].state=READY; /* 放入就绪队列中 */ 370 371 _SS=tcb[i].ss; 372 _SP=tcb[i].sp; /* 保存现场 */ 373 374 tcb[i].state=RUNNING; 375 current=i; 376 enable(); 377 } 378 379 void block(struct TCB **p) /* 阻塞原语 */ 380 { 381 struct TCB *pp; 382 383 tcb[current].state=BLOCKED; 384 385 if((*p)==NULL) 386 *p=&tcb[current]; /* 阻塞队列空,直接放入 */ 387 else 388 { 389 pp=*p; 390 while(pp->next) 391 pp=pp->next; /* 找到阻塞队列最后一个节点 */ 392 393 pp->next=&tcb[current]; /* 放入阻塞队列 */ 394 } 395 tcb[current].next=NULL; 396 swtch(); /* 重新进行CPU调度 */ 397 } 398 399 void wakeup_first(struct TCB **p) /* 唤醒队首线程 */ 400 { 401 struct TCB *pl; 402 403 if((*p)==NULL) 404 return; 405 406 pl=(*p); 407 (*p)=(*p)->next; /* 得到阻塞队列队首线程 */ 408 pl->state=READY; /* 修为就绪状态 */ 409 pl->next=NULL; 410 } 411 412 void p(semaphore *sem) 413 { 414 struct TCB **qp; 415 416 disable(); 417 sem->value=sem->value-1; 418 419 if(sem->value<0) 420 { 421 qp=&(sem->wq); 422 block(qp); 423 } 424 enable(); 425 } 426 427 void v(semaphore*sem) 428 { 429 struct TCB **qp; 430 431 disable(); 432 qp=&(sem->wq); 433 sem->value=sem->value+1; 434 435 if(sem->value>=0) 436 wakeup_first(qp); 437 438 enable(); 439 } 440 441 /////////////////////////////////////////////////////////////////////////////// 442 // buffer 443 struct buffer*Initbuf(void) 444 { 445 struct buffer *p,*pt,*pt2; 446 int i; 447 448 pt2=pt=(struct buffer*)malloc(sizeof(struct buffer)); 449 pt->sender=-1; 450 pt->size=0; 451 strcmp(pt->text,""); 452 pt->next=NULL; 453 454 for(i=0;i<NBUF-1;i++) 455 { 456 p=(struct buffer*)malloc(sizeof(struct buffer)); 457 p->sender=-1; 458 p->size=0; 459 p->text[NTEXT]='