zoukankan      html  css  js  c++  java
  • [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();
    }
    
    • 如果一段临界区太长而不适合简单的关中断来实现,可以考虑采用挂起调度器的方式
    • 唤醒调度器是一个相对较长的操作

    注意

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

    Good Good Study! Day Day Up!

  • 相关阅读:
    cgal 的初步学习
    java 代理类
    java 静态内部类
    HDU-2063-过山车(最大匹配)
    HDU-1845-Jimmy's Assignment
    HDU-1528-Card Game Cheater(二分图匹配)
    HDU-1507-Uncle Tom's Inherited Land*
    HDU-1498-50years,50colors(最大匹配, 枚举)
    HDU-1281-棋盘游戏(最大匹配,枚举)
    HDU-1179-Ollivanders(二分图最大匹配)
  • 原文地址:https://www.cnblogs.com/kdurant/p/4190216.html
Copyright © 2011-2022 走看看