【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱: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函数就明白了。

嵌入式操作系统内核原理和开发(线程状态)相关推荐

  1. 嵌入式操作系统内核原理和开发

    嵌入式操作系统内核原理和开发(开篇) 操作系统是很多人每天必须打交道的东西,因为在你打开电脑的一刹那,随着bios自检结束,你的windows系统已经开始运行了.如果问大家操作系统是什么?可能有的人会 ...

  2. 嵌入式操作系统内核原理和开发(总结篇)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 很多朋友都喜欢嵌入式操作系统的内容,但是如何实现和仿真这样一个系统一直是困扰我们的难题.现在郑 ...

  3. 嵌入式操作系统内核原理和开发(地址空间)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 不管是什么样的嵌入式cpu,它必然有自己的访问地址空间.至于这个具体的访问空间是什么,那cpu ...

  4. 嵌入式操作系统内核原理和开发(延时操作)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]            延时操作是操作系统中经常遇到的一种情形.延时的原因很多,有的时候是为了等 ...

  5. 嵌入式操作系统内核原理和开发(线程切换)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 在操作系统中,线程切换是很重要的一个环节.如果没有线程的切换,我们如何才能实现多线程的并发运行 ...

  6. 嵌入式操作系统内核原理和开发(cpu的那些事)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] cpu是数字处理系统中的一个重要环节.在我看来,单片机.微处理器.dsp都可以称作是cpu,只 ...

  7. 嵌入式操作系统内核原理和开发(实时系统中的定时器)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 关于定时器的内容,其实我们之前也讨论过,也书写过相应的代码,但是表达得比较晦涩,效率也比较低. ...

  8. 嵌入式操作系统内核原理和开发(信号量)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 之前因为工作的原因,操作系统这块一直没有继续写下去.一方面是自己没有这方面的经历,另外一方面就 ...

  9. 嵌入式操作系统内核原理和开发(优先级的修改)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 之前在和rawos作者的闲聊中,rawos作者认为实时操作系统中最大的特色就是互斥量的问题.一 ...

最新文章

  1. Nature Microbiology:火眼金睛,肠道菌群绝对定量分析擒“真凶”!
  2. 斯坦福大学科学家研发微型植入式神经刺激器
  3. java 编写命令行工具_编写命令行工具
  4. 学Python一定要知道的十段经典代码
  5. linux配置apache tomcat,linux下apache+tomcat的配置实现
  6. 【Python基础】Pandas参数设置的八个小技巧
  7. AI基础:机器学习简易入门
  8. MyEclipse移动开发教程:移动Web模拟器指南(一)
  9. C++右值引用和完美转发
  10. TechEmpower 13轮测试中的ASP.NET Core性能测试
  11. 您已从远程计算机注销,您无法从 Windows Server 2008 R2 中的远程桌面会话注销
  12. Angular 项目中使用 ECharts 图表示例
  13. 90后游戏开发毛星云跳楼自杀,8年执着国产3A梦碎
  14. 机器学习-DBSCAN密度聚类
  15. 计算机房档案管理,机房档案管理制度
  16. python逆时针画圆_python 逆时针
  17. AI测试|天猫精灵智能音箱测试策略与方法
  18. 全球及中国车险行业十四五渠道营销与竞争战略规划报告2022-2028年
  19. 线程的故事(了解线程生命周期)
  20. 介绍与评测Intel HLE与RTM技术

热门文章

  1. apache虚拟主机、日志轮询、日志统计、去版本优化
  2. hdu4747 线段树区间修改值,区间查询和及最大值即最大值位置
  3. 探究操作系统的内存分配(malloc)对齐策略
  4. JavaScript操作HTML 元素
  5. Arduino抢答器
  6. oracle 清除数据库缓存
  7. JavaSE语法基础总结
  8. 修改Win7远程桌面端口
  9. C#面向对象基础(四) 静态成员与实例成员
  10. UML类图中会涉及到的一些概念、关系