• [FreeRTOS] 临界区处理


     

     

    简介

    每个进程中访问临界资源的那段代码称为临界区(Critical Section) (临界资源是一次仅允许一个进程使用的共享资源)。
    每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。
    多个进程中涉及到同一个临界资源的临界区称为相关临界区

    程序调度法则

    进程进入临界区的调度原则是:

    1. 如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
    2. 任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。
    3. 进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
    4. 如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
    

    FreeRTOS解决方法

    开关中断

    void process_data(void)
    {
        taskENTER_CRITICAL(); //or portENTER_CRITICAL();
        x++;
        taskEXIT_CRITICAL();  //or portEXIT_CRITICAL();
    }
    
    • 抢占式上下文切换只可能在某个中断完成,所以调用taskENTER_CRITICAL()的任务可以在中断关闭的时段一直保持运行态,直到退出临界区
    • 临界区必须只具有很短的时间,否则会影响中断响应时间

    使用信号量或者互斥量

    推荐使用互斥量,因为互斥量解决了优先级翻转的问题

    void process_data(void)
    {
        if(xSemaphoreTake(xSemaphore, 10) == pdTRUE)
        {
            x++;
            xSemaphoreGive( xSemaphore );
        }
    }
    

    信号量和互斥量的最大区别是

    • 用于互斥的信号量必须归还
    • 用于同步的信号量在完成同步后变丢弃,不需要归还

    禁止任务调度

    void process_data(void)
    {
        vTaskSuspendAll();
        x++;
        xTaskResumeAll();
    }
    
    • 如果一段临界区太长而不适合简单的关中断来实现,可以考虑采用挂起调度器的方式
    • 唤醒调度器是一个相对较长的操作

    注意

    在使用临界区时,一般不允许其运行时间过长,只要进入临界区的线程还没有离开,其他所有试图进入此临界区的线程都会被挂起而进入到等待状态,并会在一定程度上影响程序的运行性能

  • 相关阅读:
    Cogs 452. Nim游戏!(博弈)
    Cogs 876. 游戏(DP)
    Cogs 2546. 取石块儿(博弈)
    Bzoj 4147: [AMPPZ2014]Euclidean Nim(博弈)
    Codevs 3002 石子归并 3(DP四边形不等式优化)
    洛谷 P1041 传染病控制
    洛谷 P1967 货车运输
    洛谷 P1038 神经网络
    洛谷 P1027 Car的旅行路线
    洛谷 P1054 等价表达式
  • 原文地址:https://www.cnblogs.com/dream397/p/15897828.html
Copyright © 2020-2023  润新知