关于多线程工作

定时中断实现任务切换
如图 4A 所示,CPU 在空闲任务循环等待,定时中断将 CPU 周期性唤回,根据任务设计
了不同的响应频度,满足条件的任务将获得CPU资源,CPU为不同任务“关照”完成后,再
次返回空闲任务,如此周而复始,对于各个任务而言,好像各自拥有一个独立的CPU,各自
独立运行。用这种思想构建的程序框架,最大的好处是任务很容易裁剪,系统能够做得很复
杂。
在充分考虑单片机中断特性(在哪里中断就返回到哪里)后,实际可行的任务切换如图
4B所示,定时中断可能发生在任务调度,随机任务执行的任何时候,图中最大的框框所示,
不管中断在何时发生,它都会正常返回,定时中断所产生的影响只在任务调度模块起作用,
即依次让不同的任务按不同的节拍就绪。任务调度会按一定的优先级执行就绪任务。
总结不同的任务需要CPU关照的频度,选择最快的那个频度来设定定时器中断的节拍,
一般选择 200Hz,或者 100Hz 都可以。另外再给每个任务设定一个节拍控制计数器 C,也就
是定时器每中断多少次后执行任务一次。例如取定时中断节拍为 200Hz,给任务设定的 C=10,
则任务执行频度为 200/10=20Hz,如果是数码管扫描,按 40Hz 不闪烁规律,则任务节拍控制
计数器 C=5 即可。在程序设计中,C 代表着任务运行的节拍控制参数,我们习惯用 delay 来
描述,不同的任务用task0,task1……来描述。
明天继续写如何用代码实现!2009-6-29
下面我们来用代码实现以上多任务程序设计思想。
首先是任务切换
while(1)
{
if(task_delay[0]==0)   task0();  //task0就绪,
if(task_delay[1]==0)   task1();  //task1就绪,
……
}
很显然,执行任务的条件是任务延时量task_delay=0,那么任务延时量谁来控制呢?定时
器啊!定时器中断对任务延时量减一直到归零,标志任务就绪。当没有任务就绪时,任务切
换本身就是一个Idle 任务。
void timer0(void) interrupt 1
{
if(task_delay[0]) task_delay[0]--;
if(task_delay[1]) task_delay[1]--;
……
}
例如 timer0 的中断节拍为 200Hz,task0_delay 初值为 10,则 task0()执行频度为
200/10=20Hz。
有了以上基础,我们来设计一个简单多任务程序,进一步深入理解这种程序设计思想。
任务要求:用单片机不同 IO 脚输出 1Hz,5Hz,10Hz,20Hz 方波信号,这个程序很短,将
直接给出。
#include "reg51.h"
#define TIME_PER_SEC 200    //定义任务时钟频率,200Hz
#define CLOCK 22118400    //定义时钟晶振,单位Hz  
#define MAX_TASK 4      //定义任务数量

extern void task0(void);  //任务声明
extern void task1(void);
extern void task2(void);
extern void task3(void);

sbit f1Hz  = P1^0;  //端口定义
sbit f5Hz  = P1^1;
sbit f10Hz = P1^2;
sbit f20Hz = P1^3;

unsigned char task_delay[4];  //任务延时变量定义

//定时器0初始化
void timer0_init(void)
{
    unsigned char i;
   for(i=0;i<MAX_TASK;i++) task_delay=0;  //任务延时量清零
    TMOD = (TMOD & 0XF0) | 0X01;        //定时器 0工作在模式 1, 16Bit定时器模
式  
    TH0 = 255-CLOCK/TIME_PER_SEC/12/256;   
  TL0 = 255-CLOCK/TIME_PER_SEC/12%256;   
   TR0 =1;  
ET0 =1;         //开启定时器和中断
}

// 系统 OS定时中断服务
void timer0(void) interrupt 1
{
    unsigned char i;
    TH0 = 255-CLOCK/TIME_PER_SEC/12/256;
    TL0 = 255-CLOCK/TIME_PER_SEC/12%256;        
    for(i=0;i<MAX_TASK;i++) if(task_delay) task_delay--;  
//每节拍对任务延时变量减1 ,减至 0  后,任务就绪。   
}

/*main主函数*/
void main(void)
{
    timer0_init();
    EA=1;//开总中断   
   while(1)
   {  
     if(task_delay[0]==0) {task0(); task_delay[0] = TIME_PER_SEC/ 2;}
  //要产生 1hz 信号,翻转周期就是 2Hz,以下同
  if(task_delay[1]==0) {task1(); task_delay[1] = TIME_PER_SEC/10;}
  //要产生 5hz 信号,翻转周期就是 10Hz,以下同
  if(task_delay[2]==0) {task2(); task_delay[2] = TIME_PER_SEC/20;}
  if(task_delay[3]==0) {task3(); task_delay[3] = TIME_PER_SEC/40;}     
   }
}

void task0(void)
{   
    f1Hz = !f1Hz;   
}

void task1(void)
{   
    f5Hz = !f5Hz;   
}

void task2(void)
{   
    f10Hz = !f10Hz;   
}

void task3(void)
{   
    f20Hz = !f20Hz;   
}

(他的程序粘贴下来我自己改了一下)

#include <reg51.h>
#define TIME_PER_SEC 200    //定义任务时钟频率,200Hz
#define CLOCK 22118400    //定义时钟晶振,单位Hz  
#define MAX_TASK 4      //定义任务数量

extern void task0(void);  //任务声明
extern void task1(void);
extern void task2(void);
extern void task3(void);

sbit f1Hz  = P1^0;  //端口定义
sbit f5Hz  = P1^1;
sbit f10Hz = P1^2;
sbit f20Hz = P1^3;

unsigned char task_delay[4];  //任务延时变量定义

//定时器0初始化
void timer0_init(void)
{
    unsigned char i;
   for(i=0;i<MAX_TASK;i++) task_delay[i]=0;  //任务延时量清零
    TMOD = (TMOD & 0XF0) | 0X01;        //定时器 0工作在模式 1, 16Bit定时器模式  
    TH0 = 220;   
      TL0 = 30;                                //定时器0定时周期10us
    TR0 =1;  
    ET0 =1;         //开启定时器和中断
}

// 系统 OS定时中断服务
void timer0(void) interrupt 1
{
    unsigned char i;
    TH0 = 220;
    TL0 = 30;        
    for(i=0;i<MAX_TASK;i++)
    {
        if(task_delay[i])
            task_delay[i]--;
        if(i==MAX_TASK)
            i=0;
    }
//每节拍对任务延时变量减1 ,减至 0  后,任务就绪。   
}

/*main主函数*/
void main(void)
{
    timer0_init();
    EA=1;//开总中断   
   while(1)
   {  
     if(task_delay[0]==0) {task0(); task_delay[0] = TIME_PER_SEC/ 2;} //执行一次后不断填充新值
  //要产生 1hz 信号,翻转周期就是 2Hz,以下同
  if(task_delay[1]==0) {task1(); task_delay[1] = TIME_PER_SEC/10;}      //执行一次后不断填充新值
  //要产生 5hz 信号,翻转周期就是 10Hz,以下同
  if(task_delay[2]==0) {task2(); task_delay[2] = TIME_PER_SEC/20;}       //执行一次后不断填充新值
  if(task_delay[3]==0) {task3(); task_delay[3] = TIME_PER_SEC/40;}     //执行一次后不断填充新值
   }
}

void task0(void)
{   
    f1Hz = !f1Hz;   
}

void task1(void)
{   
    f5Hz = !f5Hz;   
}

void task2(void)
{   
    f10Hz = !f10Hz;   
}

void task3(void)
{   
    f20Hz = !f20Hz;   
}

时间: 2024-08-10 17:18:01

关于多线程工作的相关文章

深入理解IIS的多线程工作机制

首先让我们来看看IIS里面的这2个数字:最大并发连接数,队列长度.先说这2个数字在哪里看. 最大并发连接数:在IIS中选中一个网站,右键网站名称,在右键菜单中找到并点击[管理网站]->[高级设置].打开对话框如下图: 队列长度:在IIS中选中[应用程序池],在应用程序池列表中,右键你想查看的,在右键菜单中选择[高级设置].打开如下对话框: 这两个数字表面上看是影响我们站点的并发处理能力的,但是具体是如何影响一个网站的并发处理能力的呢?要完全理解IIS的并发处理能力,除了这2个数字,实际上还有一个

程序员如何多线程工作,做个职场达人

当我正在一个很复杂的业务编写算法的紧要关头--突然,同事反映网站的某某功能不能运行了,要你给修复.接着几分钟后,你的团队负责人要求你解释一下昨天发表的有关项目的问题.以及,你的收件箱每隔5分钟就提醒你,又有新邮件了.哦no,要崩溃了! 在日常工作中很多人都会有同感?工作中突然发现的小bug,是不是蹦出来的邮件提醒,产品经理又要改功能等等不受控制的发生,在本来安稳有序的工作中该如何处理这些突发情况,不被干扰呢,现在电脑都四核八核了,你的大脑可不能单线程工作了,要学会整理自己的工作,分清轻重缓急安排

关于多线程工作内存何时会刷新的问题探讨

JMM 用来定义程序中变量的访问规则,定义者,想要屏蔽掉不同的硬件和系统造成的内存访问差异. 之前了解的JMM空也曾提到工作内存的概念,每个线程都有自己的工作内存,所有的变量多存在主内存,工作内存存储的是各个线程用到的变量 主内存的副本拷贝,工作内存之间不能直接操作对方工作内存的变量,要通过主内存作为中间介,各个线程只能操作各自的工作线程变量,无法直接操作主内存变量. 然后就是就是定义了8中原子操作,用来控制变量,分别是 lock.unlock,read.load.use.assign.stor

python 学习笔记day10-python多线程,forking,xinetd服务

xinetd服务器 配置xinetd服务 什么是xinetd xinetd可以统一管理很多服务进程,它能够: - 绑定.侦听和接受来对自服务器每个端口的请求 - 有客户访问时,调用相应的服务器程序相应 - 节约了系统内存资源 - 同时响应多个客户端的连接请求 Windows系统没有该功能 多数UNIX系统使用的是inetd实现相同的功能 配置文件解析 选项名称 说明 flags 如果只指定NAMEINARGS,那么它就使参数和inetd一样的传递 type 如果服务不在/etc/services

.NET基础拾遗(5)多线程开发基础

Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 一.多线程编程的基本概念 下面的一些基本概念可能和.NET的联系并不大,但对于掌握.NET中的多线程开发来说却十分重要.我们在开始尝试多线程开发前,应该对这些基础知识有所掌握,并且能够在操作系统层面理解多线程的运行方式. 1.1 操作系统层面的进程和线程 (1)进程 进程代表了操作系统上运行着的一个应用程序.进程拥有自己的程序块

并行处理提高工作效率

我们都知道,如今的CPU可以如此强大,和其复杂而科学的调度系统是分不开的.CPU不会傻傻的等待一件事情做完才去做另外一件事情,而是把所有的工作细化,轮询执行,这样才可以保证资源利用效率最大化. 同样,工作中也经常会遇到A事情暂时做不下去而要暂时挂起的情况,这时我们要傻傻的无限等待吗?若这样效率就大打折扣了,我们可以在此设定一个回调,马上开启另外一个线程开始另外一件B事情的运行,当B事情遇到阻塞又暂时搁浅,而A事情已经回调通知我们可以继续了,这时我们就可以马上切换到A事情上去.当这样几个事情之间来

Unity3D游戏开发之多线程及使用多线程

Unity3D游戏开发之多线程及使用多线程 Unity3D中的多线程.线程是一个相当复杂的话题,但如果掌握了它,就可以从容的使用多个硬件处理器或处理很难划分管理数据块. 如在场景中用A*算法进行大量的数据计算,变形网格中操作大量的顶点,持续的要运行上传数据到服务器,二维码识别等图像处理,如果同时你要处理很多事情或者与Unity的对象互动小可以用thread,否则使用coroutine. 线程是在程序中与其他线程同时运行的进行.在多处理器的计算机上可以做到多个线程的真正的同步,更多的线程取决于有多

.NET基础拾遗(7)多线程开发基础2

二..NET中的多线程编程 2.1 如何在.NET程序中手动控制多个线程? 最直接且灵活性最大的,莫过于主动创建.运行.结束所有线程. (1)第一个多线程程序 .NET提供了非常直接的控制线程类型的类型:System.Threading.Thread类.下面是一个简单的多线程程序: class Program { static void Main(string[] args) { Console.WriteLine("进入多线程工作模式:"); for (int i = 0; i &l

iOS之多线程

概述 程序: 一个可以运行的文件(我们写的代码) 进程  是程序执行的一个操作实体 在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcode,系统就会分别启动2个进程 通过“活动监视器”可以查看Mac系统中所开启的进程 线程:(Thread)线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行 一个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程) 比如使用酷狗播放音乐.使用迅雷下载电影,都需要在线程中