zoukankan      html  css  js  c++  java
  • ucos

     重入与不可重入:

    可重入函数指当一个函数在被调用时,同时还能被其他函数调用,且不会产生错误.
    不可重入函数则不能同时被多次调用,多次调用可能会产生错误.

    例子:某函数有一个变量为全局变量,则如果该函数有多个实例在交替运行的话,由于同时存取
    同一全局变量,导致该变量被不同实例改变而引起错误.

    信号量:
    与同一共享数据打交道(可能是全局变量,也可能是共享资源如UART,打印机等)的任务调用等待
    信号量函数OSSemPend(),处理完后调用释放信号量函数OSSemPost().
    为防止无限等待可设置等待超时.

    例子:
    //任务Task要存取共享数据,如果该数据正在被其他任务使用,则任务Task只能等待别的任务用
    //完,然后分配给任务Task使用.用完后释放该信号量,以供给其他任务使用(或者说将资源归还
    //给操作系统).
    void Task(void)
    {
        OSSemPend(...);
        perform operation;    //porcess the data
        OSSemPost(...);
    }

    信号量也可能是隐藏的.如多任务共享UART时,信号量可隐藏在驱动函数中.

    信号量操作:
    初始化/建立 INITILIZE/CREATE
    等待信号/挂起 WAIT/PEND
    给信号 SIGNAL/POST

    信号量类型:
    二进制    0/1
    计数型    0 ~ 2^width - 1
    如果某种资源只有1个,可用二进制型信号量,如RS232接口.
    如果资源有多个,可用计数型信号量,如系统缓冲区一般有多个.

    死锁:
    两个任务无限期相互等待对方控制的资源.可用信号量等待超时来化解.

    事件标志(Event Flag)
    用于任务与多个事件同步.
    可用多个事件的组合发信号给多个任务.
    可将8/16/32个事件标志组合在一起,当任务所需的事件都发生了,任务结束挂起,继续运行


    任务间通讯(Intertask Communication)
    两个途径:
    1.通过全局变量.与中断函数进行通讯只能通过全局变量.
    2.发送消息给另一个任务.

    发送消息的方式有邮箱(Mail Box)和消息队列(Message Queue)

    邮箱(Mail Box)
    一个任务通过内核服务给另一个任务发消息.
    内核提供的邮箱服务:
    邮箱内消息内容初始化;
    将消息放入邮箱(POST);
    等待有消息进入邮箱(PEND);

    例子:
    TASK1 --(POST)--> MAIL BOX --(PEND)--> TASK2

    可在主程序中创建邮箱,则在任务中就可直接使用.
    疑问:也可在任务中创建邮箱,但此时,邮箱能否接收其他任务发送消息?能否发送消息给其他任务?

    消息队列(Message Queue)
    实际上是邮箱阵列.
    任务或ISR可将消息放入消息队列(POST),一个或多个任务可从消息队列中得到消息.
    传递的消息实际上是传递的指针指向的内容.消息队列的进出通常有规则,如FIFO.

    例子:
    ISR --(POST)--> MSG QUEUE --(PEND)--> TASK

    疑问:消息队列属于某个任务?还是所有任务公用的?任务能从消息队列中取得消息,
    并执行相应的操作.任务也可以向外发送消息,但是是否应该指明发送的消息是送给谁的?
    在Windows系统的应用程序中,程序的运行是基于事件驱动,消息循环的.每个应用程序进程
    都有自己的消息队列.如一个进程1发送消息给进程2,进程2收到消息便继续往下执行,否则
    就挂起什么都不干.也即是没有事件的驱动,程序是不往下运行的.程序的运行就是依靠不
    断的消息循环来进行下去,程序从消息队列中接收自己的消息,而发送消息时需指明将消息
    送给哪个进程.

    某一个进程发送一条消息,指明了需要送给哪个进程,该消息进入系统的消息队列,系统将
    该则消息投递到目的进程的消息缓存中.而接收消息的进程则读取消息并处理消息.
    在这个过程中,系统就像一个邮局,进程发送消息就像寄信,系统投递消息就像邮递员送信.

    在uC/OS中,可以创建一个消息队列,并返回一个该消息队列的标识,用户任务就可以通过
    这个标识向队列中发送消息或接收消息,这样看来不在发送消息时指定接收消息的任务是
    可以的.但当任务较多,且创建了较多的消息队列后,多个任务使用消息队列时是否会产生
    误发送或误接收等问题.对于uC/OS中的其他类型资源如Mail Box也是如此.


    用户应用uC/OS系统的框架:

    main()
    {
        ...
        OSInit();
        ...
        OSTaskCreate();
        ...
        OSStart();
    }

    OSInit()会进行一些初始化,包括Mail Box,Queue,Memory Partition等的初始化.
    并创建OS_Idle_Task.

    OSTaskCreate()用来创建用户任务,uC/OS应该也支持动态创建任务,即在用户任务中来
    创建其他任务,并可将其删除.不过uC/OS称任务被删除后,代码仍在,只是不再调度该任
    务.而Linux则是将任务从内存中释放.这可能与CPU有关.如果是哈佛结构的(如51单片
    机),代码是存放在ROM中的,无法删除,一般对于嵌入式系统而言,多数都是属于哈佛结
    构的CPU吧.而PC机的CPU是普林斯顿结构,程序代码和数据都是存放于内存中的,当一个
    任务不再运行了,就可释放其占据的内存空间,以供其他程序使用.

    OSStart()开始进行调度.

  • 相关阅读:
    正确添加Google Adsense
    微软开发主管临别诤言
    DZ论坛重建管理员
    Cook book 第4天 第6章 层、自定义组件
    Cook Book 第二天 运行环境识别修改
    flex cookbook 学习第一天 基本知识
    C#:String类型中的CharAt
    对我学C#时的一次小回忆[一:语法篇]
    分享一段C#反射代码[Type是反射的入口][查看类型信息][动态生成对象]
    C#反射:让私有成员无所遁形
  • 原文地址:https://www.cnblogs.com/yanglin1228/p/4812080.html
Copyright © 2011-2022 走看看