在 DOS 下实现多线程

在 DOS 下实现多线程

分类: DOS编程技术 2302人阅读 评论(2) 收藏 举报

在 DOS 下实现多线程
      程序在 Turbo C 3.0 下调试通过,采用了最简单的时间片轮转法,实现了多线程的系统,程序尽量采用了最简洁的技术来实现多任务的系统,主要使用到了C标准库中的setjmp和longjmp两个函数,程序绝大部分都是采用C/C++语言书写,但是仍然不可避免的采用了三句内嵌汇编,来进行线程堆栈的切换。由于DOS下的系统调用,都是不可重入的.如果在多个线程中同时调用了DOS的系统调用,就会出现死机等问题。一般可以使用信号量来解决DOS重入问题。整个系统,是使用时钟中断处理程序,来完成任务的调度。

 

stdefine.h

  1. /* 标准头文件 */  
  2. #ifndef _STDEFINE_H_  
  3. #define _STDEFINE_H_  
  4.   
  5. /* 常量定义 */  
  6. #define TRUE  1  
  7. #define FALSE 0  
  8.   
  9. /* 标准的类型定义 */  
  10. //typedef int BOOL;  
  11. typedef unsigned char  BYTE;  
  12. typedef unsigned short WORD;  
  13. typedef unsigned long  DWORD;  
  14. typedef long     int   LONG;  
  15.   
  16. /* 定义常用的宏 */  
  17. #define LOWBYTE(value)     ( (BYTE)  ((value) & 0x00FF) )  
  18. #define HIBYTE(value)      ( (BYTE)  ((value) >> 8)     )  
  19. #define LOWWORD(value)     ( (WORD)  ((value) & 0xFFFF) )  
  20. #define HIWORD(value)      ( (WORD)  ((value) >> 16)    )  
  21. #define MAKEWORD(hi, low)  ( (WORD)  (((hi)<<8)|(low))  )  
  22.   
  23. #endif  

 

thread.h

  1. #ifndef _THREAD_H_  
  2. #define _THREAD_H_  
  3.   
  4. /* 包含头文件 */  
  5. #include "stdefine.h"  
  6.   
  7. /* 类型声明 */  
  8. typedef int (*THREADPROC)(void *argv);  
  9.   
  10. /* 函数声明 */  
  11. int InitMultiThread(unsigned short cycle); /* cycle 主线程的时间片 */  
  12. void CloseMultiThread();      
  13. /* proc 线程入口函数,argv 参数,cycle 线程时间片,返回值:线程ID */  
  14. int  CreateThread(THREADPROC proc, void *argv, WORD cycle);  
  15. void DestroyThread(int id);  
  16. void RunThread(int id);  
  17. void StopThread(int id);  
  18. void PauseThread(int t);  
  19. void KeepMainThread(int d);    //只运行主线程  
  20. #endif  

 

thread.cpp

  1. /* 包含头文件 */  
  2. #include <mem.h>  
  3. #include <string.h>  
  4. #include <stdlib.h>  
  5. #include <setjmp.h>  
  6. #include <dos.h>  
  7. #include "stdefine.h"  
  8. #include "thread.h"  
  9.   
  10. /* 常量定义 */  
  11. #define MAX_THREAD_NUM    5       //16     定义最大的线程数  
  12. #define THREAD_STACK_SIZE 256     //512    定义每个线程申请的内存  
  13. #define THREAD_DEAD       0  
  14. #define THREAD_READY      1  
  15. #define THREAD_RUNNING    2  
  16. #define THREAD_STOPPED    3  
  17.   
  18. #define _INT_1CH          0x1c  
  19.   
  20.   
  21. /* 类型定义 */  
  22. typedef struct  
  23. {  
  24.     THREADPROC proc;  
  25.     void      *argv;  
  26.     WORD       status;  
  27.     int       timer;       //当前剩余时间  
  28.     WORD       cycle;      //分配的时间片大小  
  29.     jmp_buf    jmpbuf;  
  30.     BYTE       stack[THREAD_STACK_SIZE];  
  31. } THREADITEM, PTHREADITEM;  
  32.   
  33. /* 内部全局变量定义 */  
  34. static void interrupt (*old_int_1ch)(...);  
  35. static THREADITEM thread_list[MAX_THREAD_NUM] = {0};  
  36. static int cur_thread = 0;  
  37. static int main_thread_keep=0;         //主线程标志  
  38.   
  39. extern int graph_sigle;                 //外部信号量,解决程序不能重入问题,如图形库函数不能重入  
  40.                                         //通常=1  
  41.   
  42. /* 内部函数声明 */  
  43. static void interrupt MULTI_THREAD_MAN(...);  
  44. static void changetimer(WORD t);  
  45.   
  46.   
  47. /* 函数实现 */  
  48. int InitMultiThread(unsigned short cycle)    //初始化多线程调度程序  
  49. {  
  50.     memset(thread_list, 0, sizeof(THREADITEM) * MAX_THREAD_NUM);  
  51.     cur_thread = 0;  
  52.     /* main thread cycle */  
  53.     thread_list[cur_thread].status = THREAD_RUNNING;  
  54.     thread_list[cur_thread].timer  = cycle;  
  55.     thread_list[cur_thread].cycle  = cycle;     
  56.     old_int_1ch = getvect(_INT_1CH);  
  57.     setvect(_INT_1CH, MULTI_THREAD_MAN);  
  58.     return TRUE;  
  59. }  
  60.   
  61. void CloseMultiThread()     //关闭线程序调度  
  62. {  
  63. //  changetimer(0);  
  64.     disable();  
  65.     setvect(_INT_1CH, old_int_1ch);  
  66.     enable();  
  67. }  
  68. void KeepMainThread(int d)  //选择是否只运行主线程  
  69. {  
  70.     if(d==0)  
  71.     {  
  72.         main_thread_keep=0;     //多线程  
  73.         disable();  
  74.         setvect(_INT_1CH, MULTI_THREAD_MAN);  //调度程序重新作用  
  75.         enable();  
  76.     }  
  77.     else  
  78.     {  
  79.         main_thread_keep=1;     //==1时,只运行主线程(单线程)  
  80.     }  
  81. }  
  82. int  CreateThread(THREADPROC proc, void *argv, WORD cycle)   //创建新线程  
  83. {  
  84.     int i;  
  85.     for (i=0; i<MAX_THREAD_NUM; i++)  
  86.     {  
  87.         if (thread_list[i].status == THREAD_DEAD)  
  88.         {  
  89.             thread_list[i].proc   = proc;  
  90.             thread_list[i].argv   = argv;  
  91.             thread_list[i].status = THREAD_READY;  
  92.             thread_list[i].timer  = cycle;  
  93.             thread_list[i].cycle  = cycle;  
  94.             return i;  
  95.         }  
  96.     }  
  97.     return NULL;  
  98. }  
  99.   
  100. void DestroyThread(int id)  
  101. {  
  102.     memset(&thread_list[id], 0, sizeof(THREADITEM));  
  103. }  
  104.   
  105. void RunThread(int id)   //重新开启原先被暂停的线程   
  106. {  
  107.     disable();  
  108.     thread_list[id].status = THREAD_RUNNING;  
  109.     enable();  
  110. }  
  111.   
  112. void StopThread(int id)  //用于暂时关闭副线程  
  113. {  
  114.     while(1)  
  115.     {  
  116.         if(graph_sigle==1)        //信号为1时才关闭线程  
  117.         {  
  118.             disable();  
  119.             thread_list[id].status = THREAD_STOPPED;  
  120.             enable();  
  121.             break;  
  122.         }  
  123.     }  
  124. }  
  125.   
  126. /* 内部函数实现 */  
  127. static void changetimer(WORD t)     //修改单位时间  
  128. {  
  129.     outportb(0x43, 0x3c);  
  130.     outportb(0x40, LOWBYTE(t));  
  131.     outportb(0x40, HIBYTE(t));  
  132. }  
  133.   
  134. /* 线程调度函数,是整个系统的关键 */  
  135. static void interrupt MULTI_THREAD_MAN(...)  
  136. {  
  137.     static int i;  
  138.     static int temp;  
  139.     /* 关中断 */  
  140.     disable();  
  141.     if(cur_thread==0 && main_thread_keep==1)    
  142.     {  
  143.         setvect(_INT_1CH, old_int_1ch);   //当运行到主线程时间片且main_thread_keep==1时,关闭线程调度程序  
  144.         enable();  
  145.         return;  
  146.     }  
  147.     //多线程调度  
  148.     if (--thread_list[cur_thread].timer > 0)  
  149.     {   /* 当前线程的时间片未用完,不进行线程调度 */  
  150.         enable();  /* 开中断 */  
  151.         return;  
  152.     }  
  153.   
  154.     /* 当前线程的时间片用完,进行线程调度 */  
  155.     thread_list[cur_thread].timer = thread_list[cur_thread].cycle;  /* 重新分配时间片 */  
  156.     if (!setjmp(thread_list[cur_thread].jmpbuf))  /* 保存当前线程的运行环境 */  
  157.     {   /* 开始线程调度 */  
  158.         for (i=0; i<MAX_THREAD_NUM; i++)  
  159.         {   /* 查找下一个可调度的线程 */  
  160.             cur_thread++;  
  161.             cur_thread %= MAX_THREAD_NUM;  
  162.             if (thread_list[cur_thread].status == THREAD_READY)  
  163.             {  
  164.                 /* 为新线程分配堆栈 */  
  165.                 temp = (WORD)(thread_list[cur_thread].stack);  
  166.                 temp += THREAD_STACK_SIZE;  
  167.                 asm mov sp, temp;  
  168.                 asm mov ax, ds;  
  169.                 asm mov ss, ax;  
  170.   
  171.                 /* 调用线程函数 */  
  172.                 thread_list[cur_thread].status = THREAD_RUNNING;  
  173.                 outp(0x20, 0x20);  /* 清除中断屏蔽 */  
  174.                 enable();  /* 开中断 */  
  175.                 thread_list[cur_thread].proc(thread_list[cur_thread].argv);  
  176.   
  177.                 /* 线程运行结束 */  
  178.                 disable(); /* 关中断 */  
  179.                 thread_list[cur_thread].status = THREAD_DEAD;  
  180.                 longjmp(thread_list[0].jmpbuf, 1);  /* 返回主线程 */  
  181.                 break;  
  182.             }  
  183.             else if (thread_list[cur_thread].status == THREAD_RUNNING)  
  184.             {   /* 调度线程 */  
  185.                 longjmp(thread_list[cur_thread].jmpbuf, 1);  
  186.                 break;  
  187.             }  
  188.         }  
  189.     }  
  190.     outp(0x20, 0x20);  /* 清除中断屏蔽 */  
  191.     enable();  /* 开中断 */  
  192. }  

 

main.cpp

  1. /* 包含头文件 */  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <dos.h>  
  5. #include <conio.h>  
  6. #include "thread.h"  
  7.   
  8. int graph_sigle=1;  //如果多线程中同时有DOS系统调用,用信号量隔开  
  9.   
  10. /* 以下是测试程序 */  
  11. int fun(void *n)  
  12. {  
  13.     while (1)  
  14.     {  
  15.         sound(1000);  
  16.         delay(200);  
  17.         nosound();  
  18.         delay(200);  
  19.     }  
  20. }  
  21.   
  22. int fun2(void *s)  
  23. {  
  24.     printf("%s", s);  
  25. }  
  26.   
  27. /* 演示了三个线程:主线程、fun 和 fun2 */  
  28. main()  
  29. {  
  30.     int id1;  
  31.     int id2;  
  32.     WORD i = 0;  
  33.     InitMultiThread(1);  
  34.     id1 = CreateThread(fun, NULL, 1);  
  35.     id2 = CreateThread(fun2, (void*)"hello world !/r/n", 1);  
  36.     for (i=0; i< 3; i++)delay(1000);  
  37.     while (!kbhit())  
  38.     {  
  39.         printf("rockcarry %u/r/n", i++);  
  40.     }  
  41.     getch();  
  42.     DestroyThread(id2);  
  43.     DestroyThread(id1);  
  44.     CloseMultiThread();  
  45.     nosound();  

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值