注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

独立观察员·网易

分享万岁

 
 
 

日志

 
 

[编辑][turboC][操作系统]DOS基于时间片轮转的线程调度问题  

2013-06-02 20:25:00|  分类: 原新浪博客的 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
*[turboC]DOS 基于时间片轮转的线程调度问题 (运行方式:建议使用 http://pan.baidu.com/share/link?shareid=467362&uk=2299465928 这个软件,运行时选择工具-选项中的turbo C 2.0 编译器)*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>

#define GET_INDOS 0x34
#define GET_CRIT_ERR 0x5d06
#define FINISHED 0  
#define RUNNING 1 
#define READY 2  
#define BLOCKED 3  
#define NTCB 5  
#define NTEXT 20  
#define NBUF 5  

char far *indos_ptr = 0;  *该指针变量存放INDOS标志的地址*/
char far *crit_err_ptr = 0; *该指针变量存放严重错误标志的地址*/
int current = 0;  
int timecount = 0;  *从调度至今运行的时间,一个单位约55ms*/
int TL = 1; * 时间片大小,单位为1/18.2秒,与timecount的单位一样*/
int buf[5];
int in, out;


typedef struct
{
    int value; 
    struct TCB *wq;  * 线程阻塞队列队首指针*/
}semaphore;


struct TCB
{
    unsigned char *stack;  * 线程堆栈的起始地址*/
    unsigned ss;  
    unsigned sp;  
    char state;  
    char name[10];  
    struct TCB *next;  
    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, off, seg;
   
};


typedef int (far *codeptr)();  * 定义一个函数指针类型*/
void interrupt (*old_int8)(); 

void initDos();  
void initTcb();  
int DosBusy();  
int create(char *name, codeptr code, int stackLen); 
void destroy(int id);  
void over();  
void interrupt new_int8();  
void interrupt my_swtch();  
void block(struct TCB **qp);  
void wakeup_first(struct TCB **qp);  
void P(semaphore *sem);  
void V(semaphore *sem);  
void initBuf();  
struct buffer *getbuf();  
void putbuf(struct buffer *buff); 
void insert(struct buffer **mq, struct buffer *buff); 
struct buffer *remov(struct buffer **mq, int sender);  
void send(char *receiver, char *a, int size); 
int receive(char *sender, char *b);  
int find();  
void tcb_state();  
int finished();  

* 初始化DOS,获得INDOS标志的地址和严重错误标志的地址 */
void initDos()
{
    union REGS regs;
    struct SREGS segregs;
    
    regs.h.ah = GET_INDOS;
    intdosx(&regs, &regs, &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(&regs, &regs, &segregs);
        crit_err_ptr = MK_FP(segregs.ds, regs.x.si);
    }
}

void initTcb()
{
    int id;
    for(id = 0; id < NTCB; id++)
    {
        tcb[id].stack = NULL;  * 线程堆栈的起始地址*/
        tcb[id].state = FINISHED;
        tcb[id].name[0] = '\0';
        tcb[id].next = NULL;
        tcb[id].mq = NULL;
        tcb[id].mutex.value = 1;
        tcb[id].mutex.wq = NULL;
        tcb[id].sm.value = 0;
        tcb[id].sm.wq = NULL;
    }
}

int DosBusy()
{
    if(indos_ptr && crit_err_ptr)
        return (*indos_ptr || *crit_err_ptr);  
    else
        return -1; 
}


int create(char *name, codeptr code, int stackLen)
{
    int id;
    struct int_regs far *regs;
    disable();  
    for(id = 1; id < NTCB; id++)  *寻找空的TCB*/
    {
        if(tcb[id].state == FINISHED)
        break;
    }
    if(id == NTCB)  
    {
        printf("\n  **** 线程 %s 创建失败 ****\n", name);
        return -1;
    }
   
    tcb[id].stack = (unsigned char *)malloc(stackLen);
    regs = (struct int_regs far *)(tcb[id].stack + stackLen);
    regs--;
    tcb[id].ss = FP_SEG(regs);  * 获取远地址段值*/
    tcb[id].sp = FP_OFF(regs);  *获取远地址偏移量*/
    tcb[id].state = READY;
    strcpy(tcb[id].name, name);
    
    regs->DS = _DS;  *数据段地址*/
    regs->ES = _ES;  *附加段地址*/
    regs->IP = FP_OFF(code);
    regs->CS = FP_SEG(code);
    regs->Flags = 0x200;
    regs->off = FP_OFF(over);
    regs->seg = FP_SEG(over);
    printf("\n  **** Thread %d %s has been created! ****\n", id, tcb[id].name);
    enable();  
    return id;
}

*系统或用户要求撤销线程*/
void destroy(int id)
{
    disable();  
    
    free(tcb[id].stack);
    tcb[id].stack = NULL;
    tcb[id].state = FINISHED;
    tcb[id].name[0] = '\0';
    tcb[id].next = NULL;
    tcb[id].mq = NULL;
    tcb[id].mutex.value = 1;
    tcb[id].mutex.wq = NULL;
    tcb[id].sm.value = 0;
    tcb[id].sm.wq = NULL;
    printf("\n  **** Thread%d %s has been destoryed! ****\n", id, tcb[id].name);
    enable();  
}

* 用于自动撤销线程(线程已完成) */
void over()
{
    destroy(current);  
    my_swtch();  
}

* 时间片(原来的?)到时引起的CPU调度 */
void interrupt new_int8()
{
    (*old_int8)();  *调用原来的时钟中断服务程序*/
    timecount++;  
    if(timecount < TL || DosBusy())  *时间片未到或DOS正忙*/
        return;
    my_swtch();  *调用my_swtch()进行重新调度*/
}

* 其他原因引起的CPU调度(执行完或等待事件) */
void interrupt my_swtch()
{
    int i;
    disable(); 
   * 保存现行堆栈的段址和栈顶供下次切换时用*/
    tcb[current].ss = _SS;
    tcb[current].sp = _SP;
    if(tcb[current].state == RUNNING)
        tcb[current].state = READY;
    i = find();  *查找一个新的就绪线程i*/
    if(i < 0)  * 查找失败(i=-1)*/
        i = 0;  *主线程?*/
    *切换为线程i*/
    _SS = tcb[i].ss;
    _SP = tcb[i].sp;
    tcb[i].state = RUNNING;
    current = i;
    timecount = 0;  
    enable();  *开中断*/
}



* 寻找READY状态线程的内部标识符(id) */
int find()
{
    int id;
    for(id = current + 1; id < NTCB; id++)
    {
        if(tcb[id].state == READY)
            return id;
    }
    for(id = 0; id < current; id++)
    {
        if(tcb[id].state == READY)
            return id;
    }
    return -1;
}


void tcb_state()
{
    int id;
    printf("\n  **** The current threads' state ****\n");
    for(id = 0; id < NTCB; id++)
    {
        printf("Thread%d %9s state is ", id, tcb[id].name);
        switch(tcb[id].state)
        {
            case FINISHED: puts("FINISHED"); break;
            case RUNNING: puts("RUNNING"); break;
            case READY: puts("READY"); break;
            case BLOCKED: puts("BLOCKED"); break;
        }
    }
}

* 检查除0#线程外的所有其他线程是否都已运行完 */
int finished()
{
    int id;
    for(id = 1; id < NTCB; id++)
    {
        if(tcb[id].state != FINISHED)
            return 0;
    }
    return 1;
}


void f1()
{
    int i, j, k;
    for(i = 0; i < 50; i++)
    {
        putchar('a');
     
        for(j = 0; j < 500; j++)
            for(k = 0; k < 500; k++);
    }
}


void f2()
{
    long i, j, k;
    for(i = 0; i < 30; i++)
    {
        putchar('b');
        
        for(j = 0; j < 500; j++)
            for(k = 0; k < 500; k++);
    }
}


int main()
{
    initDos();  
    initTcb(); 
   * initBuf();  */
    old_int8 = getvect(8); *获取系统原来的时钟中断服务程序的入口地址*/
    *创建0#线程*/
    strcpy(tcb[0].name, "main");
    tcb[0].state = RUNNING;
    current = 0;
   
                printf("\n The realization of thread concurrent execution, can set the time sheet size.\n");
                printf(" Thread F1 continuous output of the letters a, a total of 50 times\n");
                printf(" Thread F2 continuous output of the letters b, a total of 30 times\n");
                printf(" Please set the time slice size:");
                scanf("%d", &TL);
                printf(" Press any key to continue. . . ");
                getch();
                create("f1", (codeptr)f1, 1024);
                create("f2", (codeptr)f2, 1024);
                tcb_state();
                setvect(8, new_int8);  *为时钟中断设置新的中断服务程序*/
                my_swtch();  
                while(!finished());
               
           
        tcb_state();
        setvect(8, old_int8);
   
    tcb[0].state=FINISHED;
    tcb[0].name[0]='\0';
    printf("\n\n  Thank you for using multi task system\n");
    return 0;
}

  评论这张
 
阅读(31)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018