RT-Thread学习笔记五——临界区与临界区保护

目录

临界区:

 临界区保护方法:

1.禁用系统调度器

2.禁用中断

临界区示例代码:

临界区:

一次仅只能有一个线程访问的共享资源,可以为一个具体的硬件设备,也可以是一个变量,一个缓冲区,但是,无论软件或硬件,都只能各种线程之间互斥访问。

例如:

rt_uint32_t value=0;

此时全局变量value就是一个共享资源,每个线程中对value访问的代码就是临界区,每次只允许一个线程进入临界区。

void task1(){
      value++;  //临界区
      while(value<50){
rt_kpritf("count is %s\n",value);
  }
}

 临界区保护方法:

RT-Thread中提供了多种保护临界区的方法,具体分为以下几类

1.禁用系统调度器                   2.禁用中断

1.禁用系统调度器

将系统线程调度器锁住,直到临界区相关线程执行结束,再将调度器解锁,即可实现对临界区的保护。

void thread_entry(void* parameter)
{
        while(1)
       {
            
            rt_enter_critical();   //将线程调度器上锁,此时线程调度器仅能响应中断
            /* 以下进入临界区 */
            . . . .
            /*临界区执行完成*/

           rt_exit_critical();  //调度器解锁
        }
}

注意:仅仅锁住调度器,中断可以响应

2.禁用中断

操作系统的线程调度都是基于中断的,所以禁用中断即可实现阻止线程之间的切换,禁用中断的函数实现如下:

void thread_entry(void* parameter)
{         
       rt_base_t level;  //创建变量以使用中断关闭和中断开启函数
       while(1)
        {
             
               level = rt_hw_interrupt_disable();  //中断关闭函数
              /* 以下是临界区*/
               . . . .
         
             rt_hw_interrupt_enable(level);  中断开启函数
        }
}

注意:使用禁用中断时需要先创建变量,然后将中断关闭函数保存在变量中实现中断关闭,在开启中断时将改变量传入开启函数即可。

临界区示例代码:

#include <rthw.h>
#include <rtthread.h>
#define THREAD_PRIORITY      20
#define THREAD_STACK_SIZE    512
#define THREAD_TIMESLICE     5
/* 同时访问的全局变量 */
static rt_uint32_t cnt;
void thread_entry(void *parameter)
{
    rt_uint32_t no;
    rt_uint32_t level;
    no = (rt_uint32_t) parameter;
    while (1)
    {
        /* 关闭中断 */
        level = rt_hw_interrupt_disable();
        cnt += no;
        /* 恢复中断 */
        rt_hw_interrupt_enable(level);
        rt_kprintf("protect thread[%d]'s counter is %d\n", no, cnt);
        rt_thread_mdelay(no * 300);
    }
}
int main(void)
{
    rt_thread_t thread;
    /* 创建thread1线程 */
    thread = rt_thread_create("thread1", thread_entry, (void *)10,
                              THREAD_STACK_SIZE,
                              THREAD_PRIORITY, THREAD_TIMESLICE);
    if (thread != RT_NULL)
        rt_thread_startup(thread);
    /* 创建thread2线程 */
    thread = rt_thread_create("thread2", thread_entry, (void *)30,
                              THREAD_STACK_SIZE,
                              THREAD_PRIORITY, THREAD_TIMESLICE);
    if (thread != RT_NULL)
        rt_thread_startup(thread);
    return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(main, interrupt sample);

 现象:串口打印对cnt计算的结果,先加10,再加30,再加10依次循坏。

      如果不加临界区保护,会导致只跑一个线程,不会交替运行 

猜你喜欢

转载自blog.csdn.net/Reasally/article/details/127095936
今日推荐