嵌入式操作系统内核原理和开发(线程状态)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
从第一篇的os博客以来,谈了很多内容,有中断、切换、调度、内存、互斥和延时等等,但是线程的状态却没有涉及到,今天我们要好好说一说。说到线程的状态,按照一般的说法,主要包括就绪、延时、阻塞、阻塞超时四个状态。如果线程没有死亡的话,那么这几个状态也够用了,但是我们后来发现可能需要对某些线程进行挂起处理,这可能是出现了故障或者是为了调试使用。因此,除了上面的四个状态,我们还要补充对应的四个挂起状态,分别是挂起、延时挂起、阻塞挂起、阻塞延时挂起。
说到了线程状态,下面我们就看看常见的线程处理函数有哪些,无外乎线程创建、线程延时、线程挂起、线程恢复和线程删除等等。
RAW_U16 raw_task_create(RAW_TASK_OBJ *task_obj, RAW_U8 *task_name, RAW_VOID *task_arg, RAW_U8 task_prio, RAW_U16 time_slice, PORT_STACK *task_stack_base, RAW_U32 stack_size, RAW_TASK_ENTRY task_entry, RAW_U8 auto_start){#if (RAW_TASK_STACK_CHECK > 0)PORT_STACK *p_stack;RAW_U32 i;#endifRAW_SR_ALLOC();#if (RAW_TASK_FUNCTION_CHECK > 0)if (task_obj == 0) {return RAW_NULL_OBJECT;}if (task_prio >= CONFIG_RAW_PRIO_MAX) {return RAW_BYOND_MAX_PRIORITY;}if (task_stack_base == 0) {return RAW_NULL_POINTER;}if (task_entry == 0) {return RAW_NULL_POINTER;}#endifRAW_CRITICAL_ENTER();if (task_prio == IDLE_PRIORITY) {if (idle_task_exit) {RAW_CRITICAL_EXIT();return RAW_IDLE_EXIT;}idle_task_exit = 1;}RAW_CRITICAL_EXIT();raw_memset(task_obj, 0, sizeof(RAW_TASK_OBJ));#if (CONFIG_ROUND_ROBIN > 0)if (time_slice) {task_obj->time_total = time_slice;}else {task_obj->time_total = TIME_SLICE_DEFAULT;}task_obj->time_slice = task_obj->time_total;#endifif (auto_start)task_obj->task_state = RAW_RDY;elsetask_obj->task_state = RAW_SUSPENDED;#if (RAW_TASK_STACK_CHECK > 0)task_obj->task_stack_base = task_stack_base;p_stack = task_stack_base;for (i = 0; i < stack_size; i++) { *p_stack++ =0; }#endiftask_obj->task_stack = port_stack_init(task_stack_base, stack_size, task_arg, task_entry);task_obj->task_name = task_name; task_obj->priority = task_prio;task_create_hook(task_obj);RAW_CRITICAL_ENTER();#if (RAW_TASK_STACK_CHECK > 0)task_obj->stack_size = stack_size;list_insert(&task_head, &task_obj->stack_check_list);#endifif (auto_start) {add_ready_list_end(&raw_ready_queue, task_obj);}if (raw_os_active != RAW_OS_RUNNING) { /* Return if multitasking has not started */RAW_CRITICAL_EXIT();return RAW_OS_STOPPED;}RAW_CRITICAL_EXIT();if (auto_start) {raw_sched();}return RAW_SUCCESS;}
创建线程的函数是比较复杂的,内容长一些,参数也多一些。首先看看有哪些参数,虽然很多,但是慢慢梳理一下也不难理解,有名称、参数、优先级、时间片、堆栈起始指针、堆栈大小、入口函数和标志。整个函数基本上都是赋值的过程,最重要的其实就两个部分,一个是port_stack_init,另一个就是add_ready_list_end。前者可以对堆栈进行默认处理,比如压入一些寄存器、压入函数参数、函数指针等等,后者就是把线程加入到就绪队列。
RAW_U16 raw_sleep(RAW_U32 dly) {RAW_U16 error_status;RAW_SR_ALLOC();#if (RAW_TASK_FUNCTION_CHECK > 0)if (raw_int_nesting) {return RAW_NOT_CALLED_BY_ISR;}#endif RAW_CRITICAL_ENTER();if (dly) {/*system is locked so task can not sleep just return immediately*/if (raw_sched_lock) { RAW_CRITICAL_EXIT(); return RAW_SCHED_DISABLE;}raw_task_active->task_state = RAW_DLY;tick_list_insert(raw_task_active, dly);remove_ready_list(&raw_ready_queue, raw_task_active);}else { /*make current task to the end of ready list*/move_to_ready_list_end(&raw_ready_queue, raw_task_active);}RAW_CRITICAL_EXIT();raw_sched(); if (dly) {/*task is timeout after sleep*/error_status = block_state_post_process(raw_task_active, 0);}else {error_status = RAW_SUCCESS;}return error_status;}
我们之前也介绍过系统的延时功能。延时,就是把线程暂时从就绪队列清除出来,添加到延时队列中。当然如果参数为0,那表示作者只是希望暂时释放cpu的使用权,如果此时没有同等优先级的任务,那么下一个运行的线程还是它自己。
RAW_U16 raw_task_suspend(RAW_TASK_OBJ *task_ptr){RAW_SR_ALLOC();#if (RAW_TASK_FUNCTION_CHECK > 0)if (task_ptr == 0) {return RAW_NULL_OBJECT;}#endif if (task_ptr->priority == IDLE_PRIORITY) {return RAW_SUSPEND_TASK_NOT_ALLOWED;}RAW_CRITICAL_ENTER();if (task_ptr == raw_task_active) {if (raw_sched_lock) { RAW_CRITICAL_EXIT();return RAW_SCHED_LOCKED;}}switch (task_ptr->task_state) {case RAW_RDY:task_ptr->task_state = RAW_SUSPENDED;remove_ready_list(&raw_ready_queue, task_ptr);break;case RAW_DLY:task_ptr->task_state = RAW_DLY_SUSPENDED;break;case RAW_PEND:task_ptr->task_state = RAW_PEND_SUSPENDED;break;case RAW_PEND_TIMEOUT:task_ptr->task_state = RAW_PEND_TIMEOUT_SUSPENDED;break;case RAW_DLY_SUSPENDED:case RAW_PEND_SUSPENDED:case RAW_PEND_TIMEOUT_SUSPENDED:RAW_CRITICAL_EXIT();return RAW_SUSPENDED_AGAIN;default:#if (CONFIG_RAW_ASSERT > 0)RAW_ASSERT(0);#endifRAW_CRITICAL_EXIT();return RAW_STATE_UNKNOWN;}RAW_CRITICAL_EXIT();raw_sched(); return RAW_SUCCESS;}
挂起任务的动作其实是比较残暴的,因为此时你不知道线程处于什么状态。当然任务如果已经被挂起了,那什么也不用做了,否则就需要把任务修改为对应的挂起状态就可以了。当然如果任务是就绪态的,还得把任务清除处理来。在函数结束的时候,我们需要重新进行调度,因为很有可能当前最高优先级的线程已经发生了改变。
RAW_U16 raw_task_resume(RAW_TASK_OBJ *task_ptr){RAW_SR_ALLOC();#if (RAW_TASK_FUNCTION_CHECK > 0)if (task_ptr == 0) {return RAW_NULL_OBJECT;}#endif RAW_CRITICAL_ENTER();switch (task_ptr->task_state) {case RAW_RDY:case RAW_DLY:case RAW_PEND:case RAW_PEND_TIMEOUT:RAW_CRITICAL_EXIT();return HAS_NOT_SUSPENDED;case RAW_SUSPENDED:task_ptr->task_state = RAW_RDY;add_ready_list(&raw_ready_queue, task_ptr);break;case RAW_DLY_SUSPENDED:task_ptr->task_state = RAW_DLY;break;case RAW_PEND_SUSPENDED:task_ptr->task_state = RAW_PEND;break;case RAW_PEND_TIMEOUT_SUSPENDED:task_ptr->task_state = RAW_PEND_TIMEOUT;break;default:#if (CONFIG_RAW_ASSERT > 0)RAW_ASSERT(0);#endifRAW_CRITICAL_EXIT();return RAW_STATE_UNKNOWN;}RAW_CRITICAL_EXIT();raw_sched(); return RAW_SUCCESS;}
恢复函数其实就是挂起函数的逆向操作。如果任务没有被挂起,那么什么也不用做。否则就需要把任务的状态修改为对应的非挂起状态,当然该就绪的线程还得加入到就绪队列当中去。同时在函数结束之前不忘调度一下,说不定刚刚释放的这个线程就是优先级最高的那个线程。
RAW_U16 raw_task_delete(RAW_TASK_OBJ *task_ptr){RAW_SR_ALLOC();#if (RAW_TASK_FUNCTION_CHECK > 0)if (task_ptr == 0) {return RAW_NULL_OBJECT;}if (raw_int_nesting) {return RAW_NOT_CALLED_BY_ISR;}#endifif (task_ptr->priority == IDLE_PRIORITY) {return RAW_DELETE_TASK_NOT_ALLOWED;}RAW_CRITICAL_ENTER();if (task_ptr == raw_task_active) {if (raw_sched_lock) { RAW_CRITICAL_EXIT();return RAW_SCHED_LOCKED;}}switch (task_ptr->task_state) {case RAW_RDY:remove_ready_list(&raw_ready_queue, task_ptr);break;case RAW_SUSPENDED:break;case RAW_DLY: /* Task is only delayed, not on any wait list */case RAW_DLY_SUSPENDED:tick_list_remove(task_ptr);break;case RAW_PEND:case RAW_PEND_SUSPENDED:case RAW_PEND_TIMEOUT:case RAW_PEND_TIMEOUT_SUSPENDED:tick_list_remove(task_ptr);list_delete(&task_ptr->task_list);break;default:#if (CONFIG_RAW_ASSERT > 0)RAW_ASSERT(0);#endifRAW_CRITICAL_EXIT();return RAW_STATE_UNKNOWN;} task_ptr->task_state = RAW_DELETED; #if (RAW_TASK_STACK_CHECK > 0)/*make after_delete_list to right position*/after_delete_list = task_ptr->stack_check_list.next;if (after_delete_list == &task_head) {after_delete_list = task_head.next;}list_delete(&task_ptr->stack_check_list);#endifRAW_CRITICAL_EXIT();raw_sched(); return RAW_SUCCESS;}
删除函数的动作其实是比较残忍的,因为此时你不清楚线程已经执行到哪一步了,拥有了那些资源,正在处理哪些资源,所以没事不要用这个函数。这里做的只是把任务从就绪队列、等待队列和阻塞队列清除出来,但是真正善后的工作要比这多得多,如果有兴趣,你看看linux的exit函数就明白了。
嵌入式操作系统内核原理和开发(线程状态)相关推荐
- 嵌入式操作系统内核原理和开发
嵌入式操作系统内核原理和开发(开篇) 操作系统是很多人每天必须打交道的东西,因为在你打开电脑的一刹那,随着bios自检结束,你的windows系统已经开始运行了.如果问大家操作系统是什么?可能有的人会 ...
- 嵌入式操作系统内核原理和开发(总结篇)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 很多朋友都喜欢嵌入式操作系统的内容,但是如何实现和仿真这样一个系统一直是困扰我们的难题.现在郑 ...
- 嵌入式操作系统内核原理和开发(地址空间)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 不管是什么样的嵌入式cpu,它必然有自己的访问地址空间.至于这个具体的访问空间是什么,那cpu ...
- 嵌入式操作系统内核原理和开发(延时操作)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 延时操作是操作系统中经常遇到的一种情形.延时的原因很多,有的时候是为了等 ...
- 嵌入式操作系统内核原理和开发(线程切换)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 在操作系统中,线程切换是很重要的一个环节.如果没有线程的切换,我们如何才能实现多线程的并发运行 ...
- 嵌入式操作系统内核原理和开发(cpu的那些事)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] cpu是数字处理系统中的一个重要环节.在我看来,单片机.微处理器.dsp都可以称作是cpu,只 ...
- 嵌入式操作系统内核原理和开发(实时系统中的定时器)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 关于定时器的内容,其实我们之前也讨论过,也书写过相应的代码,但是表达得比较晦涩,效率也比较低. ...
- 嵌入式操作系统内核原理和开发(信号量)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 之前因为工作的原因,操作系统这块一直没有继续写下去.一方面是自己没有这方面的经历,另外一方面就 ...
- 嵌入式操作系统内核原理和开发(优先级的修改)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 之前在和rawos作者的闲聊中,rawos作者认为实时操作系统中最大的特色就是互斥量的问题.一 ...
最新文章
- Nature Microbiology:火眼金睛,肠道菌群绝对定量分析擒“真凶”!
- 斯坦福大学科学家研发微型植入式神经刺激器
- java 编写命令行工具_编写命令行工具
- 学Python一定要知道的十段经典代码
- linux配置apache tomcat,linux下apache+tomcat的配置实现
- 【Python基础】Pandas参数设置的八个小技巧
- AI基础:机器学习简易入门
- MyEclipse移动开发教程:移动Web模拟器指南(一)
- C++右值引用和完美转发
- TechEmpower 13轮测试中的ASP.NET Core性能测试
- 您已从远程计算机注销,您无法从 Windows Server 2008 R2 中的远程桌面会话注销
- Angular 项目中使用 ECharts 图表示例
- 90后游戏开发毛星云跳楼自杀,8年执着国产3A梦碎
- 机器学习-DBSCAN密度聚类
- 计算机房档案管理,机房档案管理制度
- python逆时针画圆_python 逆时针
- AI测试|天猫精灵智能音箱测试策略与方法
- 全球及中国车险行业十四五渠道营销与竞争战略规划报告2022-2028年
- 线程的故事(了解线程生命周期)
- 介绍与评测Intel HLE与RTM技术