• rtt线程管理学习笔记


    rtt线程管理

    rt_thread结构体

    线程由这个结构体控制(官方文档

    /* 线程控制块 */
    struct rt_thread
    {
        /* rt 对象 */
        char        name[RT_NAME_MAX];     /* 线程名称 */
        rt_uint8_t  type;                   /* 对象类型 */
        rt_uint8_t  flags;                  /* 标志位 */
    
        rt_list_t   list;                   /* 对象列表 */
        rt_list_t   tlist;                  /* 线程列表 */
    
        /* 栈指针与入口指针 */
        void       *sp;                      /* 栈指针 */
        void       *entry;                   /* 入口函数指针 */
        void       *parameter;              /* 参数 */
        void       *stack_addr;             /* 栈地址指针 */
        rt_uint32_t stack_size;            /* 栈大小 */
    
        /* 错误代码 */
        rt_err_t    error;                  /* 线程错误代码 */
        rt_uint8_t  stat;                   /* 线程状态 */
    
        /* 优先级 */
        rt_uint8_t  current_priority;    /* 当前优先级 */
        rt_uint8_t  init_priority;        /* 初始优先级 */
        rt_uint32_t number_mask;
    
        ......
    
        rt_ubase_t  init_tick;               /* 线程初始化计数值 */
        rt_ubase_t  remaining_tick;         /* 线程剩余计数值 */
    
        struct rt_timer thread_timer;      /* 内置线程定时器 */
    
        void (*cleanup)(struct rt_thread *tid);  /* 线程退出清除函数 */
        rt_uint32_t user_data;                      /* 用户数据 */
    };
    
    
    • 可以设置线程栈大小,对于较大资源的MCU可以设置1K或者2K的大小

    • 线程五种状态,同一时间之允许一个线程在处理器中处理

    • 可以设置优先级,优先级为0最高,最大支持0~255,一般使用32优先级

    • 每个线程都可以设置时间片
      相同优先级时间片轮转

    • 线程不能进入死循环,如果这样比他优先级低的线程都不会运行

    • 线程状态转换 注:RT-Thread 中,实际上线程并不存在运行状态,就绪状态和运行状态是等同的。
      线程状态转换图

    • 空闲线程,这是系统提供最低优先级的线程,永远为就绪态,当没有其他线程存在时,可以系统自动调用,通常是死循环,在rtt中有特殊用处,

      若某线程运行完毕,系统将自动删除线程:自动执行 rt_thread_exit() 函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭状态,不再参与系统调度,然后挂入 rt_thread_defunct 僵尸队列(资源未回收、处于关闭状态的线程队列)中,最后空闲线程会回收被删除线程的资源。

      空闲线程也提供了接口来运行用户设置的钩子函数,在空闲线程运行时会调用该钩子函数,适合钩入功耗管理、看门狗喂狗等工作。

    • rt_thread_create() 创建一个动态线程,使用 rt_thread_init() 初始化一个静态线程,动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化 heap 之后才能使用 create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。

      rt_thread_t rt_thread_create(const char* name,
                                  void (*entry)(void* parameter),
                                  void* parameter,
                                  rt_uint32_t stack_size,
                                  rt_uint8_t priority,
                                  rt_uint32_t tick);
      


    对于运行出错或不适用的线程可以删除

    rt_err_t rt_thread_delete(rt_thread_t thread);
    


    初始化线程

    rt_err_t rt_thread_init(struct rt_thread* thread,
                            const char* name,
                            void (*entry)(void* parameter), void* parameter,
                            void* stack_start, rt_uint32_t stack_size,
                            rt_uint8_t priority, rt_uint32_t tick);
    

    脱离线程

    rt_err_t rt_thread_detach (rt_thread_t thread);
    

    启动线程

    rt_err_t rt_thread_startup(rt_thread_t thread);
    

    线程睡眠

    rt_err_t rt_thread_sleep(rt_tick_t tick);
    rt_err_t rt_thread_delay(rt_tick_t tick);
    rt_err_t rt_thread_mdelay(rt_int32_t ms);
    

    线程实例

    #include <rtthread.h>
    
    #define THREAD_PRIORITY         25
    #define THREAD_STACK_SIZE       512
    #define THREAD_TIMESLICE        5
    
    static rt_thread_t tid1 = RT_NULL;
    
    /* 线程 1 的入口函数 */
    static void thread1_entry(void *parameter)
    {
        rt_uint32_t count = 0;
    
        while (1)
        {
            /* 线程 1 采用低优先级运行,一直打印计数值 */
            rt_kprintf("thread1 count: %d
    ", count ++);
            rt_thread_mdelay(500);
        }
    }
    
    ALIGN(RT_ALIGN_SIZE)
    static char thread2_stack[1024];
    static struct rt_thread thread2;
    /* 线程 2 入口 */
    static void thread2_entry(void *param)
    {
        rt_uint32_t count = 0;
    
        /* 线程 2 拥有较高的优先级,以抢占线程 1 而获得执行 */
        for (count = 0; count < 10 ; count++)
        {
            /* 线程 2 打印计数值 */
            rt_kprintf("thread2 count: %d
    ", count);
        }
        rt_kprintf("thread2 exit
    ");
        /* 线程 2 运行结束后也将自动被系统脱离 */
    }
    
    /* 线程示例 */
    int thread_sample(void)
    {
        /* 创建线程 1,名称是 thread1,入口是 thread1_entry*/
        tid1 = rt_thread_create("thread1",
                                thread1_entry, RT_NULL,
                                THREAD_STACK_SIZE,
                                THREAD_PRIORITY, THREAD_TIMESLICE);
    
        /* 如果获得线程控制块,启动这个线程 */
        if (tid1 != RT_NULL)
            rt_thread_startup(tid1);
    
        /* 初始化线程 2,名称是 thread2,入口是 thread2_entry */
        rt_thread_init(&thread2,
                       "thread2",
                       thread2_entry,
                       RT_NULL,
                       &thread2_stack[0],
                       sizeof(thread2_stack),
                       THREAD_PRIORITY - 1, THREAD_TIMESLICE);
        rt_thread_startup(&thread2);
    
        return 0;
    }
    
    /* 导出到 msh 命令列表中 */
    MSH_CMD_EXPORT(thread_sample, thread sample);
    
    
  • 相关阅读:
    vscode vue代码提示
    解决VMware nat service等服务不能启动
    vscode突然无法格式化代码
    【必看精贴】微信网页分享开发,配置本地调试
    ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'name' of undefined
    python使用mysql数据库
    pycharm下载第三方包
    canvas绘制网络字体
    解决npm 下载速度慢的问题
    【已解决】canvas跨域问题
  • 原文地址:https://www.cnblogs.com/sunnylinry/p/15019319.html
Copyright © 2020-2023  润新知