基于DOS的多任务系统的实现
#include<stdio.h>
#include<stdlib.h>
#include <time.h>
#include<dos.h>
/*定义TCB状态*/
#define FINISHED 0
#define RUNNING 1
#define READY 2
#define BLOCKED 3
#define NTCB 5 /*定义最大空闲TCB个数*/
#define TC 2 /*定义时间片长度*/
#define NBUF 6 /*定义缓冲区大小*/
#define GET_INDOS 0x34
#define GET_CRIT_ERR 0x5d06
struct TCB{
unsigned char *stack; /*线程堆栈起始地址*/
unsigned ss; /*堆栈段址*/
unsigned sp; /*堆栈指针*/
char state; /*线程状态*/
char name[15]; /*线程外部标识符*/
struct TCB *next;
}tcb[NTCB];
/*初始化堆栈时使用*/
struct int_regs{
unsigned bp, di, si, ds, es, dx, cx, bx, ax, ip, cs, flags, off, seg;
};
char fpub[3];
int current= -1; /*定义一个当前TCB下标的全局变量*/
int timecount = 0; /*定义时间片*/
char far *indos_ptr = 0; /*该指针变量存放INDOS表示的地址*/
char far *crit_err_ptr = 0; /*该指针变量存放严重错误标志的地址*/
void interrupt (*old_int8)(void);/*旧的时钟中断处理程序*/
typedef int (far *codeptr)(void); /*定义了一个函数指针类型*/
int buffer[NBUF] = {-1,-1,-1,-1,-1,-1}; /*生产者消费者中的缓冲区*/
int in = 0;
int out = 0;
typedef struct{
int value;
struct TCB *wq;
}semaphore;
semaphore mutex={1,NULL},empty={NBUF,NULL},full={0,NULL},Mutex2={1,NULL}; /*生产者消费者中的信号量*/
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 DosBusy(void)
{
if(indos_ptr && crit_err_ptr)
return (*indos_ptr || *crit_err_ptr);
else
return -1;
}
int finished(void)
{
int i;
for(i=1; i<NTCB; i++)
if(tcb[i].state != FINISHED)
return 0;
return 1;
}
int Seeknext()
{
int i,ks;
i=current+1;
ks=0;
disable();
while(ks<NTCB)
{
if(tcb[i].state==READY)
{
return i;
}
i++;
ks++;
i=i%NTCB;
}
printf("Seeknext tcb is error!!\n");
enable();
}
void interrupt my_swtch(void)
{
disable();/*开中断*/
/*保护正在执行的线程current的现场,暂停它的执行*/
tcb[current].ss=_SS;
tcb[current].sp=_SP;
if(tcb[current].state==RUNNING)
tcb[current].state=READY;
/*找到新的就绪线程i*/
current=Seeknext();
tcb[current].state=RUNNING;
/*切换堆栈,恢复线程i的现场,把CPU分派给它*/
_SS=tcb[current].ss;
_SP=tcb[current].sp;
/*重新开始计时*/
timecount=0;
enable();/*关中断*/
}
void interrupt new_int8(void)
{
/*调用原来的时钟中断服务程序*/
(*old_int8)();
/*进行计时*/
timecount++;
/*当前线程的时间片到否*/
if(timecount >= TC)
if(!DosBusy())
{
/*调用my_swtch进行重新调度*/
my_swtch();
}
}
void Destroy(int i)
{
if(tcb[i].state==RUNNING)
{
disable();
tcb[i].state=FINISHED;
free(tcb[i].stack);
enable();
}
return;
}
void over(void)
{
Destroy(current);
printf("%s is finished!\n", tcb[current].name);
my_swtch();
}
void tcb_state()
{
int i;
printf("These are the information of all threads: \n");
for(i=0;i<NTCB-1;i++)
{
printf("the key word of the thread is : %d\n the name of thread is : %s\n the state of the thread is ",i,tcb[i].name);
switch(tcb[i].state)
{
case (1): printf("Running \n");break;
case (2): printf("Ready \n");break;
case (3): printf("Blocked\n");break;
case (0): printf("Finished\n");break;
}
}
}
/*创建线程*/
int create(char *name, codeptr code, int stacklen)
{
int i = 0;
struct int_regs *temp;
while(tcb[i].state != FINISHED) /*查找空闲TCB块*/
i++;
if(i == NTCB) return -1; /*没有空闲TCB块可用*/
strcpy(tcb[i].name, name);
tcb[i].state = READY;
tcb[i].stack = (unsigned char*)malloc(stacklen); /*为新线程分配私有堆栈空间*/
tcb[i].stack = tcb[i].stack + stacklen;
/*初始化新线程的私有堆栈*/
temp = (struct int_regs *)tcb[i].stack-1;
temp->ds = _DS;
temp->es = _ES;
temp->flags = 0x200;
temp->ip = FP_OFF(code);
temp->cs = FP_SEG(code);
temp->off = FP_OFF(over); /*将over函数压入堆栈,线程结束自动执行*/
temp->seg = FP_SEG(over);
tcb[i].ss = FP_SEG(temp);
tcb[i].sp = FP_OFF(temp);
return i;
}
void block(semaphore *sem)
{
struct TCB *p;
disable();
tcb[current].state = BLOCKED;
p = sem->wq;
if(p == NULL){
sem->wq = &tcb[current];
}
else{
while(p->next != NULL)
p = p->next ;
p->next = &tcb[current];
}
tcb[current].next = NULL;
my_swtch();
enable();
}
void wakeup(semaphore *sem)
{
struct TCB *p;
disable();
p = sem->wq;
if(p != NULL){
p->state = READY;
sem->wq = sem->wq->next;
}
enable();
}
void wait(semaphore *sem)
{
disable();
sem->value = sem->value - 1;
if(sem->value < 0)
{
printf("\nthe thread of %s is blocked\n",tcb[current].name);
block(sem);
}
enable();
}
void signal(semaphore *sem)
{
disable();
sem->value = sem->value + 1;
if(sem->value <= 0)
wakeup(sem);
enable();
}
void proceducer()
{
int i, j, k;
for(i = 1; i <=13;i++){
wait(&empty);
wait(&mutex);
buffer[in] = i*i;
printf("%s puts a number of %d in the buffer \n",tcb[current].name, buffer[in]);
/*for(j=0; j<10000; j++)
for(k=0; k<10000; k++);*/
in = (in +1) % NBUF;
signal(&mutex);
signal(&full);
}
}
void consumer()
{
int i, j, k;
for(i = 1; i<=7;i++){
wait(&full);
wait(&mutex);
printf("consumer gets the number of %d from the buffer\n", buffer[out]);
buffer[out] = -1;
/*for(j=0; j<1000; j++)
for(k=0; k<10000; k++);*/
out = (out+1) % NBUF;
signal(&mutex);
signal(&empty);
}
}
void f1()
{
int i,j,k;
wait(&Mutex2);
strcpy(fpub,"f1");
signal(&Mutex2);
for(i=1;i<=22;i++)
{
wait(&Mutex2);
printf("%s is running !\n",fpub);
signal(&Mutex2);
for(j=0;j<10000;j++)
for(k=0;k<10000;k++);
}
}
void f2()
{
int i,j,k;
wait(&Mutex2);
/*做放入数的操作*/
strcpy(fpub,"f2");
signal(&Mutex2);
for(i=1;i<=33;i++)
{
wait(&Mutex2);
printf("%s is running !\n",fpub);
signal(&Mutex2);
for(j=0;j<10000;j++)
for(k=0;k<10000;k++);
}
}
void InitTcb()/*TCB的初始化*/
{
int i;
for(i=0;i<NTCB;i++)
{
tcb[i].state=FINISHED;
tcb[i].name[0]='\0';
tcb[i].next=NULL;
}
}
int main(void)
{
InitDos();
InitTcb();
old_int8 = getvect(8);
strcpy(tcb[0].name, "main");
tcb[0].state = RUNNING;
current = 0 ;
create("proceducerOne", (codeptr)proceducer, 1024);
create("consumer", (codeptr)consumer, 1024);
/*create("proceducerTwo", (codeptr)proceducer, 1024);
create("f1",(codeptr)f1,1024);
create("f2",(codeptr)f2,1024);*/
tcb_state(NTCB);
setvect(8, new_int8);
my_swtch();
while(!finished()) ;
strcpy(tcb[0].name, "\0");
tcb[0].state = FINISHED;
setvect(8, old_int8);
printf("\n");
tcb_state(NTCB);
printf("\nMulti_task system terminated.\n");
getchar();
return 0;
}