File  View VskBlog About
程序在 Turbo C 3.0 下调试通过,采用了最简单的时间片轮转法,实现了多线程的系统,程序尽量采用了最简洁的技术来实现多任务的系统,主要使用到了C标准库中的setjmp和longjmp两个函数,程序绝大部分都是采用C/C++语言书写,但是仍然不可避免的采用了三句内嵌汇编,来进行线程堆栈的切换。由于DOS下的系统调用,都是不可重入的.如果在多个线程中同时调用了DOS的系统调用,就会出现死机等问题。一般可以使用信号量来解决DOS重入问题。整个系统,是使用时钟中断处理程序,来完成任务的调度。
                      
                    // stdefine.h
                    
                    /* 标准头文件 */  
                    #ifndef _STDEFINE_H_  
                    #define _STDEFINE_H_  
                      
                    /* 常量定义 */  
                    #define TRUE  1  
                    #define FALSE 0  
                      
                    /* 标准的类型定义 */  
                    //typedef int BOOL;  
                    typedef unsigned char  BYTE;  
                    typedef unsigned short WORD;  
                    typedef unsigned long  DWORD;  
                    typedef long     int   LONG;  
                      
                    /* 定义常用的宏 */  
                    #define LOWBYTE(value)     ( (BYTE)  ((value) & 0x00FF) )  
                    #define HIBYTE(value)      ( (BYTE)  ((value) >> 8)     )  
                    #define LOWWORD(value)     ( (WORD)  ((value) & 0xFFFF) )  
                    #define HIWORD(value)      ( (WORD)  ((value) >> 16)    )
                    #define MAKEWORD(hi, low)  ( (WORD)  (((hi)<<8)|(low))  )
                    #endif
                    
                    
                      // thread.h
                    
                    #ifndef _THREAD_H_  
                    #define _THREAD_H_  
                      
                    /* 包含头文件 */  
                    #include "stdefine.h"  
                      
                    /* 类型声明 */  
                    typedef int (*THREADPROC)(void *argv);  
                      
                    /* 函数声明 */  
                    int InitMultiThread(unsigned short cycle); /* cycle 主线程的时间片 */  
                    void CloseMultiThread();      
                    /* proc 线程入口函数,argv 参数,cycle 线程时间片,返回值:线程ID */
                    int  CreateThread(THREADPROC proc, void *argv, WORD cycle);  
                    void DestroyThread(int id);  
                    void RunThread(int id);  
                    void StopThread(int id);  
                    void PauseThread(int t);  
                    void KeepMainThread(int d);    //只运行主线程  
                    #endif
                    
                    
                      // thread.cpp
                    
                    /* 包含头文件 */  
                    #include <mem.h>  
                    #include <string.h>  
                    #include <stdlib.h>  
                    #include <setjmp.h>  
                    #include <dos.h>  
                    #include "stdefine.h"  
                    #include "thread.h"  
                      
                    /* 常量定义 */  
                    #define MAX_THREAD_NUM    5       //16     定义最大的线程数  
                    #define THREAD_STACK_SIZE 256     //512    定义每个线程申请的内存  
                    #define THREAD_DEAD       0  
                    #define THREAD_READY      1  
                    #define THREAD_RUNNING    2  
                    #define THREAD_STOPPED    3  
                      
                    #define _INT_1CH          0x1c  
                      
                      
                    /* 类型定义 */  
                    typedef struct  
                    {  
                        THREADPROC proc;  
                        void      *argv;  
                        WORD       status;  
                        int       timer;       //当前剩余时间  
                        WORD       cycle;      //分配的时间片大小  
                        jmp_buf    jmpbuf;  
                        BYTE       stack[THREAD_STACK_SIZE];  
                    } THREADITEM, PTHREADITEM;  
                      
                    /* 内部全局变量定义 */  
                    static void interrupt (*old_int_1ch)(...);  
                    static THREADITEM thread_list[MAX_THREAD_NUM] = {0};  
                    static int cur_thread = 0;  
                    static int main_thread_keep=0;         //主线程标志  
                      
                    extern int graph_sigle;                 //外部信号量,解决程序不能重入问题,如图形库函数不能重入  
                                                            //通常=1  
                      
                    /* 内部函数声明 */  
                    static void interrupt MULTI_THREAD_MAN(...);  
                    static void changetimer(WORD t);  
                      
                      
                    /* 函数实现 */  
                    int InitMultiThread(unsigned short cycle)    //初始化多线程调度程序  
                    {  
                        memset(thread_list, 0, sizeof(THREADITEM) * MAX_THREAD_NUM);  
                        cur_thread = 0;  
                        /* main thread cycle */  
                        thread_list[cur_thread].status = THREAD_RUNNING;  
                        thread_list[cur_thread].timer  = cycle;  
                        thread_list[cur_thread].cycle  = cycle;     
                        old_int_1ch = getvect(_INT_1CH);  
                        setvect(_INT_1CH, MULTI_THREAD_MAN);  
                        return TRUE;  
                    }  
                      
                    void CloseMultiThread()     //关闭线程序调度  
                    {  
                    //  changetimer(0);  
                        disable();  
                        setvect(_INT_1CH, old_int_1ch);  
                        enable();  
                    }  
                    void KeepMainThread(int d)  //选择是否只运行主线程  
                    {  
                        if(d==0)  
                        {  
                            main_thread_keep=0;     //多线程  
                            disable();  
                            setvect(_INT_1CH, MULTI_THREAD_MAN);  //调度程序重新作用  
                            enable();  
                        }  
                        else  
                        {  
                            main_thread_keep=1;     //==1时,只运行主线程(单线程)  
                        }  
                    }  
                    int  CreateThread(THREADPROC proc, void *argv, WORD cycle)   //创建新线程  
                    {  
                        int i;  
                        for (i=0; i<MAX_THREAD_NUM; i++)  
                        {  
                            if (thread_list[i].status == THREAD_DEAD)  
                            {  
                                thread_list[i].proc   = proc;  
                                thread_list[i].argv   = argv;  
                                thread_list[i].status = THREAD_READY;  
                                thread_list[i].timer  = cycle;  
                                thread_list[i].cycle  = cycle;  
                                return i;  
                            }  
                        }  
                        return NULL;  
                    }  
                      
                    void DestroyThread(int id)  
                    {  
                        memset(&thread_list[id], 0, sizeof(THREADITEM));  
                    }  
                      
                    void RunThread(int id)   //重新开启原先被暂停的线程   
                    {  
                        disable();  
                        thread_list[id].status = THREAD_RUNNING;  
                        enable();  
                    }  
                      
                    void StopThread(int id)  //用于暂时关闭副线程  
                    {  
                        while(1)  
                        {  
                            if(graph_sigle==1)        //信号为1时才关闭线程  
                            {  
                                disable();  
                                thread_list[id].status = THREAD_STOPPED;  
                                enable();  
                                break;  
                            }  
                        }  
                    }  
                      
                    /* 内部函数实现 */  
                    static void changetimer(WORD t)     //修改单位时间  
                    {  
                        outportb(0x43, 0x3c);  
                        outportb(0x40, LOWBYTE(t));  
                        outportb(0x40, HIBYTE(t));  
                    }  
                      
                    /* 线程调度函数,是整个系统的关键 */  
                    static void interrupt MULTI_THREAD_MAN(...)  
                    {  
                        static int i;  
                        static int temp;  
                        /* 关中断 */  
                        disable();  
                        if(cur_thread==0 && main_thread_keep==1)    
                        {  
                            setvect(_INT_1CH, old_int_1ch);   //当运行到主线程时间片且main_thread_keep==1时,关闭线程调度程序  
                            enable();  
                            return;  
                        }  
                        //多线程调度  
                        if (--thread_list[cur_thread].timer > 0)  
                        {   /* 当前线程的时间片未用完,不进行线程调度 */  
                            enable();  /* 开中断 */  
                            return;  
                        }  
                      
                        /* 当前线程的时间片用完,进行线程调度 */  
                        thread_list[cur_thread].timer = thread_list[cur_thread].cycle;  /* 重新分配时间片 */  
                        if (!setjmp(thread_list[cur_thread].jmpbuf))  /* 保存当前线程的运行环境 */  
                        {   /* 开始线程调度 */  
                            for (i=0; i<MAX_THREAD_NUM; i++)  
                            {   /* 查找下一个可调度的线程 */  
                                cur_thread++;  
                                cur_thread %= MAX_THREAD_NUM;  
                                if (thread_list[cur_thread].status == THREAD_READY)  
                                {  
                                    /* 为新线程分配堆栈 */  
                                    temp = (WORD)(thread_list[cur_thread].stack);  
                                    temp += THREAD_STACK_SIZE;  
                                    asm mov sp, temp;  
                                    asm mov ax, ds;  
                                    asm mov ss, ax;  
                      
                                    /* 调用线程函数 */  
                                    thread_list[cur_thread].status = THREAD_RUNNING;  
                                    outp(0x20, 0x20);  /* 清除中断屏蔽 */  
                                    enable();  /* 开中断 */  
                                    thread_list[cur_thread].proc(thread_list[cur_thread].argv);  
                      
                                    /* 线程运行结束 */  
                                    disable(); /* 关中断 */  
                                    thread_list[cur_thread].status = THREAD_DEAD;  
                                    longjmp(thread_list[0].jmpbuf, 1);  /* 返回主线程 */  
                                    break;  
                                }  
                                else if (thread_list[cur_thread].status == THREAD_RUNNING)  
                                {   /* 调度线程 */  
                                    longjmp(thread_list[cur_thread].jmpbuf, 1);  
                                    break;  
                                }  
                            }  
                        }  
                        outp(0x20, 0x20);  /* 清除中断屏蔽 */  
                        enable();  /* 开中断 */  
                    } 
                    
                    
                      // main.cpp
                    
                    /* 包含头文件 */  
                    #include <stdio.h>  
                    #include <stdlib.h>  
                    #include <dos.h>  
                    #include <conio.h>  
                    #include "thread.h"  
                      
                    int graph_sigle=1;  //如果多线程中同时有DOS系统调用,用信号量隔开  
                      
                    /* 以下是测试程序 */  
                    int fun(void *n)  
                    {  
                        while (1)  
                        {  
                            sound(1000);  
                            delay(200);  
                            nosound();  
                            delay(200);  
                        }  
                    }  
                      
                    int fun2(void *s)  
                    {  
                        printf("%s", s);  
                    }  
                      
                    /* 演示了三个线程:主线程、fun 和 fun2 */  
                    main()  
                    {  
                        int id1;  
                        int id2;  
                        WORD i = 0;  
                        InitMultiThread(1);  
                        id1 = CreateThread(fun, NULL, 1);  
                        id2 = CreateThread(fun2, (void*)"hello world !/r/n", 1);  
                        for (i=0; i< 3; i++)delay(1000);  
                        while (!kbhit())  
                        {  
                            printf("rockcarry %u/r/n", i++);  
                        }  
                        getch();  
                        DestroyThread(id2);  
                        DestroyThread(id1);  
                        CloseMultiThread();  
                        nosound();  
                    }
                    
                    

转载自【在 DOS 下实现多线程】 http://t.csdnimg.cn/kp0Rs



Esc or Alt-X to exit title Home/PgUp/PgDn/End ←↑↓→