【RT-Thread学习笔记】02:RT-Thread线程管理

1 线程管理功能特点

在操作系统中,线程是实现任务的载体。RT-Thread中的线程调度是基于抢占式的。

2 线程的工作机制
2.1 线程控制块

它是操作系统用于管理线程的数据结构,存放线程的基本信息,比如优先级、线程名称、状态等,也包含线程与线程之间链接用的链表结构、线程等待事件集合等。

2.2 线程的重要属性

(1)线程栈
RT-Thread线程具有独立的栈,当进行线程切换时,会将当前线程上下文保存在栈中。还存放函数中的局部变量。

(2)线程状态
线程包含5种状态:初始、就绪、运行、挂起、关闭。

(3)线程优先级
RT-Thead最大支持256个线程优先级0-255,数值越小的优先级越高,0为最高优先级。

(4)时间片
每个线程都有时间片参数,但时间片仅对优先级相同的就绪状态线程有效。

(5)线程的入口函数
线程控制块的entry是线程的入口函数,它是线程实现预期功能的函数,有两种代码模式:
无限循环模式
在实时系统中,线程通常是被动式的,等待外界事件的发生,而后进行相应的服务。

		void thread_entry(void* paramenter)
        {
            while (1)
            {
                /* 等待事件的发生 */
                /* 对事件进行服务、进行处理 */
            }
        }

线程不能陷入死循环,必须要有让出CPU使用权的操作,比如在循环中调用延时函数或主动挂起。
顺序执行或有限次循环模式
一次性线程,在执行完毕后,线程将被系统自动删除。

		static void thread_entry(void* parameter)
        {
        /* 处理事务#1/
        ...
        /* 处理事务#2/
        ...
        /* 处理事务#3/
        }

(6)线程错误码
为每一个线程都配备了一个变量,用于保存错误码。错误码有以下几种:

 		#define RT_EOK           0 /* 无错误*/
        #define RT_ERROR         1 /* 普通错误*/
        #define RT_ETIMEOUT      2 /* 超时错误*/
        #define RT_EFULL         3 /* 资源已满*/
        #define RT_EEMPTY        4 /* 无资源*/
        #define RT_ENOMEM        5 /* 无内存*/
        #define RT_ENOSYS        6 /* 系统不支持*/
        #define RT_EBUSY         7 /* 系统忙*/
        #define RT_EIO           8 /* IO错误*/
        #define RT_EINTR         9 /* 中断系统调用*/
        #define RT_EINVAL        10 /* 非法参数*/
2.3 线程状态切换

在这里插入图片描述
注意,RT-Thread中,实际上线程并不存在运行状态,就绪状态和运行状态是等同的。

2.4 系统线程
  • 它包括空闲线程和主线程。
  • 若某线程运行完毕,系统将自动删除线程:自动执行rt_thread_exit()函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭状态,不再参与系统调度,然后挂入rt_thread_defunct僵尸队列(资源未回收,处于关闭状态的线程队列)中,最后空闲线程会回收被删除线程的资源。
  • 空闲线程也提供了接口来运行用户设置的钩子函数,在空闲线程运行时会调用该钩子函数,适合钩入功耗管理、看门狗、喂狗等操作。
3 线程的管理方式
  • 动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(create),静态线程由用户分配栈空间与线程句柄。
3.1创建和删除线程

可以通过下面这个函数创建动态线程,前提是先在rtconfig,h中使能动态堆(#define RT_USING_HEAP ):

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_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_thread_create()创建的线程,可以使用rt_thread_delete()这个函数删除线程,但它仅仅是把相应的线程状态更改为RT_THREAD_CLOSE状态,然后放入rt_thread_defunct队列中;真正删除是由空闲线程删除的。

3.2 初始化和脱离线程

rt_thread_detach()操作的是rt_thread_init()初始化的线程控制块,而rt_thread_delete()操作的是rt_thread_create()创建的句柄。

3.3 启动

rt_thread_startuo将创建或初始化后的线程调入相应优先级的就绪队列。

3.4 获得当前线程

一段相同的代码可能会被多个线程执行,在执行的时候可以通过rt_thread_self(void)函数获得当前执行的线程句柄。

3.5 线程让出CPU资源

rt_thread_yield() 和 rt_schedule(),前者执行后,当前线程换出,相同优先级的将被执行;后者是执行后,当前线程并不一定被换出,即使被换出,也不会放到就绪线程链表的尾部,而是选取优先级最高的线程执行。

3.6 线程睡眠

线程睡眠可以使用下面这三个函数接口:

	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);

调用它们可以使当前线程挂起一段指定的时间,当这个时间过后,线程会被唤醒并再次进入就绪状态。

3.7 控制线程

如果想控制线程的话,比如动态更改线程的优先级,用下面这个接口:

	rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg);

rt_err_t表示Type for error number。

3.8 设置和删除空闲钩子

空闲钩子函数是空闲线程的钩子函数,如果设置了空闲钩子函数,就可以在系统执行空闲线程时自动执行空闲钩子函数来做一些其他事情,比如系统指示灯。设置和删除空闲钩子的接口如下:

        rt_err_t rt_thread_idle_sethook(void (*hook)(void));
        rt_err_t rt_thread_idle_delhook(void (*hook)(void));

需要注意的是,空闲线程是状态永远为就绪状态,设置的钩子函数必须保证空闲线程在任何时刻都不会处于挂起状态,例如rt_thread_delay()(延时)、rt_sem_take()(获取信号量)等可以导致线程挂起的函数都不能使用。

3.9 设置调度器钩子

如果想知道在某个时刻发生了什么样的线程切换,可以通过调用下面的函数接口设置一个相应的钩子函数:

        void  rt_scheduler_sethook(void  (*hook)(struct  rt_thread*from,  struct  rt_thread* to));

在线程切换时,这个钩子将会被调用。但请注意在这个钩子函数中,基本上不允许调用系统API,更不应该导致当前运行的上下文挂起。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值