rt-thread的软件结构之线程调度与管理

本文详细解读rt-thread的软件结构,包括组件如DeviceFS、POSIX和图形界面,核心内核模块,线程概念、调度算法与控制,以及空闲线程和钩子函数的应用。重点介绍了线程状态、优先级管理和关键接口,适合深入理解RTOS工作原理。
摘要由CSDN通过智能技术生成

学习目标:

 


学习内容:rt-thread的软件结构

1.组件component:shell command 命令行指令

                                 Device FS     设备虚拟文件系统

                                POSIX            可移植操作系统接口

                                Lwlp:               tcp / ip栈

                                gui                  图形界面

2.Kernel 内核:      kservice.c  object.c  scheduler.c thread.c ipc.c mem.c mempool.c device.c module.c

3.Porting 移植:   

4.Hardware and Device : 硬件和外设

2.线程

线程的存在让系统具有可以并行处理问题的能力,根据优先级顺序完成了系统的分层。

在线程调度器中,中断处理函数,调度器的上锁部分和禁止中断的代码是不可抢占的。

为了顺利完成优先级的调度,采用了队列和链表的数据结构形式来实现调度任务。


关于所谓的基于位图的优先级算法可以降低复杂度的说法(未解决)

所谓的线程控制块:

线程控制块是操作系统控制线程的一种数据结构,他会存放线程的名称,优先级,线程与线程之间连接用的链表结构,线程的等待事件等。

在rt_thread中,线程控制块由struct rt_thread表示。另一种表示方式为rt_thread_t 表示的是线程的句柄(handle),二者的关系为 typedef struct rt_thread*  rt_thread_t

所谓的线程状态:

即使是多任务系统,一个时间内也只能允许一个线程在处理器中运行,在RT_thread的操作系统中,一个线程主要包含5种运行状态:

1.Rt_Thread_init       线程初始状态,当线程刚开使创建时就处于这个状态,这个状态下的线程不参与系统的任务调度。

2.Rt_thread_suspend   挂起,阻塞态。线程此时被挂起:他可能因为此时的资源不可用而挂起等待,也可能因线程主动延时一段时间而被挂起。这个状态下,线程不参与调度。

3.Rt_thread_ready       就绪状态。线程正在运行;或者当前线程运行完让出处理器后,操作系统寻找更高级的就绪态线程运行。

4.rt_thread_running     运行态。系统当前正在运行,在单核的系统中,只有rt_thread_self()函数返回的线程处于这个状态,在多核系统中则无此限制。

5.rt_thread_close       线程的结束态,当线程运行结束时将处于这个状态,线程不参与线程的调度。

线程的整个生命周期中,就是以上几种状态相互切换的过程。

 

空闲线程:

rt-thread在操作系统中提供了空闲线程,空闲线程具有最低的优先级,当系统中无线程需要运行时才会执行空闲线程。

所谓的钩子函数:用户提供的一段代码,在系统运行的某一路径上设置一个钩子,当系统经过这个位置时,转而执行钩子函数,

然后再返回到它的正常路径上。

空闲线程和钩子函数可以搭配使用,比如系统空闲的时候可以执行一些特定的任务,比如系统运行指示灯闪烁,电源管理等,真正的线程删除函数也是放在了空闲线程中(这话待理解)

调度器相关接口:

调度器初始化:

初始化调度器需要使用的全局变量

void rt_system_scheduler(void);

启动调度器:

void rt_system_scheduler_start(void);

执行调度:
void rt_scheduler(void);

设置调度器钩子:

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

hook函数的声明:

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

from 表示系统所需要切换出的线程控制块指针。

to     表示系统所要切换到的线程控制块指针

在编写自己的钩子函数时,稍有不慎就会影响到整个系统,基本不允许调用系统的API,更不应该导致当前运行的上下文挂起。

线程的相关接口:

线程的创建

rt_thread_t rt_thread_creat(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_thread_delete()函数对应的是rt_thread_create()创建的动态线程,而rt_thread_detach()对应的是rt_thread_init()创建的静态线程。

线程启动函数:

rt_err_t  rt_thread_startup(rt_thread_t thread);

通过线程启动函数可以将线程的状态改编为就绪状态,并放到相应的优先级队列中等待调度,如果新启动的线程优先级比当前的优先级高,则马上切换。

当前的线程:

获得当前正在执行的线程句柄:

rt_thread_t  rt_thread_self(void);

如果调度器还有启动,则返回RT_NULL。不要在中断服务函数中调用该函数,因为该函数并不能准确的反应当前执行的线程。

线程让出处理器:

rt_err_t  rt_thread_yield(void)

线程主动要求让出处理器资源,调度器选择相同优先级下的下一个线程进行执行,但其仍然在就绪队列中。

线程动作:从就绪优先级列表中删除,挂载到优先级队列链表尾部,激活调度器进行上下文的切换。

线程的睡眠:

就是当前线程的延时函数:

rt_err_t  thread_sleep(rt_tick_t tick)

rt_err_t thread_dealy(rt_tick_t tick)

l两个函数的作用相同,都可以是当前的线程挂起指定的时间,该时间过后线程会再次被唤醒进入就绪状态。

线程挂起函数:

当进行某些系统API的调用时,(比如 rt__delay,rt_sem_take,rt_mb_recv)将会主动激活线程挂起函数:

rt_err_t rt_thread_suspend(rt_thread_t thread);

通常不使用rt_thread_suspend来挂起线程本身,如果非要用,需要在挂起后立即调用rt-shedule()函数来触发上下文的切换

线程的恢复:

rt_err_t   thread_resume(rt_thread_t thread)

线程的控制:

当需要对线程进行如修改优先级等命令时:

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

初始化空闲线程:

系统在运行工程中必须存在一个最终可以运行的程序,调用空闲线程初始化函数:

void rt_thread_idle_init(void);

空闲线程运行时自动调用空闲钩子函数:

void rt_thread_idle_setkook(void(*hook)(void));

空闲钩子函数位于优先级最低的空闲线程中,因而该钩子函数不得引起线程挂起操作。

(空闲线程应该永远为就绪状态,所以不应该被挂起)

在rt_thread的使用过程中,经常提到关于上下文的概念,那么其上下文主要包括:

1.中断服务历程(其工作在非线程的执行环境下,为一种特权模式,中断服务是一种高于任何线程的存在)

2.普通线程

3.空闲线程

 

 


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值