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

独立观察员·网易

分享万岁

 
 
 

日志

 
 

[编辑][turboC][操作系统]线程 生产者与消费者问题  

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

  下载LOFTER 我的照片书  |
*[turboC]线程 生产者与消费者问题 */
#include
#include
#include
#include

#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; * 时间片大小*/
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;  
    semaphore mutex;  * 接收线程的消息队列的互斥信号量*/
}tcb[NTCB];  *线程数组*/

* 线程的私有堆栈,保存现场信息 */
struct int_regs
{
    unsigned BP, DI, SI, DS, ES, DX, CX, BX, AX, IP, CS, Flags, off, seg;
    *CS为代码段寄存器,IP为指令指针寄存器,CPU将CS:IP指向的内容当作指令执行;
    标志寄存器(Flags Register,FR)又称程序状态字(Program Status Word,PSW),这是一个存放条件标志、控制标志寄存器,主要用于反映处理器的状态和运算结果的某些特征及控制指令的执行;
    */
};

* 消息缓冲区节点 */
struct buffer
{
    int sender;  * 消息发送者的内部标识*/
    int size;  * 消息长度<=NTEXT个字节*/
    char text[NTEXT];  * 消息正文*/
    struct buffer *next;  * 指向下一个消息缓冲区的指针*/
}*freebuf;   *空闲消息缓冲队列*/

semaphore mutex = {1,NULL};
semaphore empty = {5, NULL};
semaphore full = {0, NULL};

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].mutex.value = 1;
        tcb[id].mutex.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].mutex.value = 1;
    tcb[id].mutex.wq = NULL;
    printf("\n  **** Thread%d %s has been destoryed! ****\n", id, tcb[id].name);
    enable();  
}

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

* 时间片到时引起的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();  *开中断*/
}

* 插入线程到阻塞队列 */
void block(struct TCB **qp)
{
    struct TCB *tcbp;  *临时指针*/
    tcb[current].state = BLOCKED;
    if((*qp) == NULL)  * 若阻塞队列为空,队首指向当前线程*/
        (*qp) = &tcb[current];
    else   *否则插入队尾*/
    {
        tcbp = (*qp);
        while(tcbp->next != NULL)
            tcbp = tcbp->next;
        tcbp->next = &tcb[current];  * 插入队尾*/
    }
    tcb[current].next = NULL;
    my_swtch();  * CPU调度*/
}

* 唤醒阻塞队列队首进程 */
void wakeup_first(struct TCB **qp)
{
    struct TCB *tcbp;
    if((*qp) == NULL)
        return;
    tcbp = (*qp);
    (*qp )= (*qp)->next;  * 阻塞队列队首指向下一个线程*/
    tcbp->state = READY;
    tcbp->next = NULL;
}

* 对信号量的P操作 */
void P(semaphore *sem)
{
    struct TCB **qp;
    disable();  * 关中断*/
    sem->value--; *  空闲资源数减1*/
    if(sem->value < 0)  * 没有空闲资源*/
    {
        qp = &(sem->wq);
        block(qp);  * 插入线程到阻塞队列*/
    }
    enable();  * 开中断*/
}

* 对信号量的V操作 */
void V(semaphore *sem)
{
    struct TCB **qp;
    disable();  
    sem->value++; 
    if(sem->value <= 0)  * 原来value<=-1,说明阻塞队列中有进程*/
    {
        qp = &(sem->wq);   *取得队首指针*/
        wakeup_first(qp);   *唤醒阻塞队列队首进程*/
    }
    enable();  
}

* 初始化消息缓冲区 */
void initBuf()
{
    struct buffer *bufp, *buff;
    int i;
    
    *初始化首节点*/
    buff = (struct buffer *)malloc(sizeof(struct buffer));
    buff->sender = -1;
    buff->size = 0;
    buff->text[0] = '\0';
    freebuf = bufp = buff;
    
    *初始化其它节点*/
    for(i = 1; i < NBUF; i++)
    {
        buff = (struct buffer *)malloc(sizeof(struct buffer));
        buff->sender = -1;
        buff->size = 0;
        buff->text[0] = '\0';
        bufp->next = buff;  *把各个节点链接起来*/
        bufp = buff;
    }
    bufp->next = NULL;  *尾节点处理*/
}

* 寻找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;
}


* 不断计算1至20的平方,并将结果放入buf中 */
void producer()
{
    int i,j,k;
    int tmp;
    for(i = 1; i <= 20; i++)
    {
        tmp = i * i;
        P(&empty);  *empty最大为5;*/
        P(&mutex);  *初始为1;*/
        buf[in] = tmp;
        printf("%d(in) ", buf[in]);
        in = (in + 1) % 5;
        V(&mutex);
        V(&full);  *初始为0;*/
        for(j = 0; j < 100; j++) 
    for(k = 0; k < 100; k++);
    }
}

* 不断从缓冲中取出结果,并打印出来 */
void consumer()
{
    int i,j,k;
    int tmp;
    for(i = 1; i <= 20; i++)
    {
        P(&full);
        P(&mutex);
        tmp = buf[out];
        out = (out + 1) % 5;
        V(&mutex);
        V(&empty);
        printf("%d(out) ", tmp);
for(j = 0; j < 100; j++) 
    for(k = 0; k < 100; k++);
    }
}


int main()
{
    initDos();  
    initTcb(); 
    initBuf();  

    old_int8 = getvect(8); *获取系统原来的时钟中断服务程序的入口地址*/
    *创建0#线程*/
    strcpy(tcb[0].name, "main");
    tcb[0].state = RUNNING;
    current = 0;
   
                printf("\n Realization of producers and consumers of the synchronization problem\n");
                printf(" Thread producer and consumer shared buffer buf which can store 5 integer\n");
                printf(" Thread producer continuous calculation of 1 to 20 square, and put the result into buf\n");
                printf(" Thread consumer continue to extract results from the buffer, and print it out\n");
                printf(" Press any key to continue. . .  ");
                getch();
                in = out = 0;
                create("producer", (codeptr)producer, 1024);
                create("consumer", (codeptr)consumer, 1024);
                tcb_state();
                TL = 1;
                setvect(8, new_int8);  
                my_swtch(); 
                while(!finished());
               
           
        tcb_state();
        
        printf("\n In addition to thread 0 other thread has been performed, press any key to end.. ");
        getch();
        
        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;
}

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

历史上的今天

评论

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

页脚

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