赞
踩
复杂任务分解为单个独立的可调度的单元,每个单元对应的程序实体为线程。
线程调度为抢占式,即从线程就绪列表中找出优先级最高的线程,然后运行。若线程优先级相同,则执行时间片轮转方式调度线程,单位为一个时钟节拍。
创建线程的时候,可以配置线程的时间片参数。时间片仅对优先级相同的就绪线程有效。
时间片的作用是约束线程单次运行的时长,其单位是系统时钟节拍(OS Tick)。
例如:A:10 B:5,则A执行10个节拍,B执行5个节拍。
除了中断处理函数、调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的,包括线程调度器自身。0 优先级代表最高优先级,最低优先级留给空闲线程使用;
初始状态———就绪状态——运行状态——挂起状态——关闭状态
初始状态,线程刚创建还未开始运行时处于的状态,此状态下,线程不参与调度。
就绪状态,线程具备运行条件的状态,等待被调度器调度执行。
运行状态,线程正在运行。
挂起状态,也称为阻塞状态。由于资源不可用或线程主动延时一段时间,而进入的状态。线程不能执行。
关闭状态,线程运行结束处于的状态。此时线程不参与调度。
涉及到的系统调用函数,在后面的学习会进行详细讲解。此处进行简单的说明:
rt_thread_create/init() 创建或初始化一个线程,此线程处于初始状态。
rt_thread_startup() 函数使得初始化状态的线程进入到就绪状态。
rt_thread_delay(),rt_sem_take(), rt_mutex_take() 等函数使得运行状态的线程进入到挂起状态。
rt_thread_resume(), rt_sem_release() 等函数使得挂起状态的线程返回到就绪状态。
rt_thread_delete/detach() 函数将挂起状态的线程更改为关闭状态。
rt_thread_exit(),处于运行状态的线程,运行结束,在线程的最后部分调用此函数,将状态更改为关闭状态。
空闲状态:优先级最低,永远为就绪态,不被挂起。 用处:回收被删除线程资源(回收僵尸线程)
rt_thread_yield():当前线程被换出,相同优先级的下一个就绪线程将被执行。
rt_schedule():当前线程并不一定被换出,而是在系统中选取就绪的优先级最高的线程执行。
入口函数是线程实现预期功能的函数。线程的入口函数由用户设计,一般有以下两种形式:
即在while(1)函数中循环
- void thread_entry(void *parameter)
- {
- while(1)
- {
- /* 线程处理 */
- }
- }
不会一直循环,执行完毕后被系统删除
RT-Thread 提供了先管理相关的系统函数:包含:创建 / 初始化线程、启动线程、运行线程、删除 / 脱离线程 等。
静态创建线程 动态创建线程两种方式
RT-Thread 内核采用面向对象的设计思想进行设计,系统级的基础设施都是一种内核对象,例如线程,信号量,互斥量,定时器等。
内核对象分为两类:静态内核对象和动态内核对象,静态内核对象通常放在RW 段和 ZI 段中,在系统启动后在程序中初始化;动态内核对象则是从内存堆中创建的,而后手工做初始化。
线程控制块是操作系统用于管理线程的一个数据结构,它会存放线程的一些信息,例如优先级、线程名称、线程状态等。
线程控制块也包含线程与线程之间连接用的链表结构,线程等待事件集合等。
- 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; /* 用户数据 */
- };
- typedef struct rt_thread *rt_thread_t;
在 RT-Thread 中,要创建一个线程,并使得它能够被执行,需要两步:
不用动态分配内存,运行效率高,实时性好。用户分配栈空间和线程句柄。
内存不可释放,只能使用rt_thread_detach() 函数将该线程控制块脱离对象管理器。
- static rt_uint8_t thread1_stack[512]; //线程栈
- static struct rt_thread thread1; //线程控制块
- rt_thread_init(&thread1, //线程handle
- "thread1", //线程名称
- thread1_entry, //线程入口函数
- RT_NULL, //线程入口参数
- &thread1_stack[0], //线程栈地址
- sizeof(thread1_stack), //线程栈大小
- 15, //线程优先级
- 5); //线程时间片
- rt_thread_startup(&thread2); //线程进入就绪态
参数简单,内存可以控制释放,用rt_thread_delete() 函数就会将这段申请的内存空间重新释放到内存堆中。
内存大小由系统分配,比静态效率低
- static rt_thread_t thread_id = RT_NULL;
- thread_id = rt_thread_create("dynamic_th", //名称
- dynamic_entry, //线程代码
- RT_NULL, //参数
- 1024, //栈大小
- 15, //优先级
- 20); //时间片
- if (thread_id != RT_NULL)
- rt_thread_startup(thread_id); //线程进入就绪态
- else
- rt_kprintf("dynamic_thread create failure\n");
- return RT_EOK;
线程创建成功,返回线程的控制块指针,也可称为线程句柄。
创建失败,则返回 RT_NULL。
线程创建完成后,需要使其进入就绪状态,也就是启动线程。可以通过调用 rt_thread_startup() 函数来完成。其函数原型为:
- rt_err_t rt_thread_startup(rt_thread_t thread)
调用此函数成功后,会将线程放到相应优先级队列中等待调度。如果新启动的线程优先级比当前优先级高,将立即切换到这个线程。
参数 thread ,线程句柄,即线程控制块的指针。
线程启动成功,返回 RT_EOK;启动失败,则返回 -RT_ERROR。
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
-
- #include <rtthread.h>
-
- #define THREAD_PRIORITY 25
- #define THREAD_STACK_SIZE 512
- #define THREAD_TIMESLICE 5
-
- void thread_entry(void *parameter)
- {
- rt_uint32_t count = 0;
-
- while(1)
- {
- /* 线程运行,打印计数 */
- rt_kprintf("thread run: %d\n", count ++);
- rt_thread_mdelay(500);
- }
- }
-
- int main(void)
- {
- rt_thread_t tid = RT_NULL;
-
- /* 创建线程, 名称是 thread_test, 入口是 thread_entry*/
- tid = rt_thread_create("thread_test",
- thread_entry, RT_NULL,
- THREAD_STACK_SIZE,
- THREAD_PRIORITY, THREAD_TIMESLICE);
-
- /* 线程创建成功,则启动线程 */
- if (tid != RT_NULL)
- {
- rt_thread_startup(tid);
- }
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。