(一)状态
线程通过调用函数 rt_thread_create/init() 进入到 | 初始状态(RT_THREAD_INIT) | 初始状态的线程通过调用函数 rt_thread_startup() 进入到 | 就绪状态(RT_THREAD_READY) | 就绪状态的线程被调度器调度后进入 | 运行状态(RT_THREAD_RUNNING) | 当处于运行状态的线程调用 rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv()
等函数或者获取不到资源时,将进入到
| 挂起状态(RT_THREAD_SUSPEND) | 处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到 | 就绪状态 | 挂起状态的线程,如果调用 rt_thread_delete/detach() 函数,将更改为 | 关闭状态(RT_THREAD_CLOSE) | 而运行状态的线程,如果运行结束,就会在线程的最后部分执行 rt_thread_exit() 函数,将状态更改为 | 关闭状态。 |
(二)API
创建:
- 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);
参数 描述
thread 线程句柄,它应该是由 rt_thread_init 进行初始化的线程句柄。
返回 ——
RT_EOK 线程脱离成功
-RT_ERROR 线程脱离失败
线程睡眠
- 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);
线程挂起
rt_err_t rt_thread_suspend (rt_thread_t thread);
恢复线程
rt_err_t rt_thread_resume (rt_thread_t thread);
控制线程
rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void* arg);
线程让出资源
rt_thread_yield() 当前线程被置于最末
rt_schedule() 按照优先级放置
获取当前线程
rt_thread_t rt_thread_self(void);
(三)挂起实验
rt_thread_suspend 可以把某个线程挂起,在某个时候恢复
尽管官方不怎么推荐使用者使用这个函数,但毕竟还是有相当的实用性,我目前有这个需求,所以进行了一些尝试。
1-初始化两个线程
- static void rt_init_thread_entry(void *parameter)
- {
- rt_thread_t led_thread, printf_thread;
- /* Initialization RT-Thread Components */
- #ifdef RT_USING_COMPONENTS_INIT
- rt_components_init();
- #endif
- /* Create led thread */
- led_thread = rt_thread_create("led",
- led_thread_entry, RT_NULL,
- 256, 20, 20);
- if (led_thread != RT_NULL)
- rt_thread_startup(led_thread);
- printf_thread = rt_thread_create("print period",
- printf_period, RT_NULL,
- 256, 20, 20);
- if (printf_thread != RT_NULL)
- rt_thread_startup(printf_thread);
- }
2-在printf控制台打印线程里面每次循环都挂起一次
- // led thread entry
- static void printf_period(void *parameter)
- {
- rt_kprintf("heart break start\n");
- while (1)
- {
- rt_kprintf("heart break\n");
- //
- rt_thread_suspend(rt_thread_self());
- }
- }
3-在led线程里面唤醒
- static void led_thread_entry(void *parameter)
- {
- rt_hw_led_init();
- rt_kprintf("start\n");
- while (1)
- {
- rt_hw_led_on();
- rt_thread_delay(RT_TICK_PER_SECOND);
- rt_hw_led_off();
- rt_thread_delay(RT_TICK_PER_SECOND);
- rt_thread_resume(printf_thread);
- }
- }
然而奇怪的事情发生了,串口每隔1s时间打印一串字符,并不是如我想象的那样打印一次立即挂起。
(四)解决方法
仔细查看文档后发现,挂起是不能够立即生效的,想要立即生效要进行上下文调度,可以用rt_schedule 引起这个调度:
- static void printf_period(void *parameter)
- {
- rt_kprintf("heart break start\n");
- while (1)
- {
- rt_kprintf("heart break\n");
- //
- rt_thread_suspend(rt_thread_self());
- rt_schedule();
- }
- }
。
|