4.RT-Thread中的线程?
/**
 * 线程结构
 */
struct rt_thread {
    /** Object对象 */
    char        name[RT_NAME_MAX];                      /**<
线程的名字 */
    rt_uint8_t  type;                                   /**< 对象的类型 */
    rt_uint8_t  flags;                                  /**< 线程的标志 */
#ifdef RT_USING_MODULE
    void       *module_id;                              /**< 应用模块的ID */
#endif
    rt_list_t   list;                                   /**< 对象链表 */
    rt_list_t   tlist;                                  /**< 线程链表 */
    void       *sp;                                     /**< 栈顶指针 */
    void       *entry;                                  /**< 入口函数 */
    void       *parameter;                              /**< 附加參数 */
    void       *stack_addr;                             /**< 栈底地址 */
    rt_uint16_t stack_size;                             /**< 线程栈的大小 */
    rt_err_t    error;                                  /**< 线程执行的错误码 */
    rt_uint8_t  stat;                                   /**< 线程的状态 */
    rt_uint8_t  current_priority;                       /**< 线程的当前优先级 */
    rt_uint8_t  init_priority;                          /**< 线程的初始优先级 */
 
#if RT_THREAD_PRIORITY_MAX > 32
    rt_uint8_t  number;         /**< 线程优先级相应的组号: current_priority >> 3 */
    rt_uint8_t  high_mask;      /**< 线程位号掩码: (1 << 位号) 位号: (current_priority & 7) */
#endif
    rt_uint32_t number_mask;    /**< 组号掩码: (1 << 组号) */
#if defined(RT_USING_EVENT)
    rt_uint32_t event_set;      /** 线程的事件集 */
    rt_uint8_t  event_info;     /** 多事件的逻辑关系: 与/或/非 */
#endif
    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;                              /**< 私实用户数据 */
};
总的来看。线程皆有由几类成员组成:object,栈相关信息。优先级信息,事件,定时器信息,私有数据指针。在RT-Thread中提供的线程接口函数都是环绕线程的各种状态展开的。

/*
 * 线程的状态定义
 */
#define RT_THREAD_INIT                  0x00                /**<
初始化状态 */
#define RT_THREAD_READY                 0x01                /**<
就绪状态 */
#define RT_THREAD_SUSPEND               0x02                /**<
挂起状态 */
#define RT_THREAD_RUNNING               0x03                /**<
执行状态 */
#define RT_THREAD_BLOCK                 RT_THREAD_SUSPEND   /**<
堵塞状态 */
#define RT_THREAD_CLOSE                 0x04                /**<
关闭/结束状态 */

处于初始化状态的接口函数有:rt_thread_init,rt_thread_create
这两个函数的差别在于一个是静态的初始化一个线程实体,还有一个是动态的创建线程实体再来初始化。


/*******************************************************************************************
** 函数名称: rt_thread_init
** 函数功能: 静态初始化线程实例
** 入口參数: thread 线程对象句柄
**    name 线程的名字
**    entry 线程的入口函数
**    parameter 附加參数
**    stack_start 栈底指针
**    stack_size 栈的大小
**    priority 线程的优先级
**    tick 线程的初始滴答数(能执行的时间片值)
** 返 回 值: 成功返回RT_EOK
** 调    用: rt_thread_init
*******************************************************************************************/
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_ASSERT(thread != RT_NULL);
    RT_ASSERT(stack_start != RT_NULL);
    /** 初始化线程内嵌的对象结构 */
    rt_object_init((rt_object_t)thread, RT_Object_Class_Thread,
name);
    /** 初始化线程实例 */
    return _rt_thread_init(thread,
                           name,
                           entry,
                           parameter,
                           stack_start,
                           stack_size,
                           priority,
                           tick);
}


/*******************************************************************************************
** 函数名称: rt_thread_create
** 函数功能: 动态的创建线程
** 入口參数: name 线程的名字
**    entry 线程的入口
**    parameter 附加參数
**    stack_size 线程栈的大小
**    priority 线程的优先级
**    tick 线程的初始化滴答数
** 返 回 值: 线程对象句柄
** 调    用:
*******************************************************************************************/
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)
{
    struct rt_thread *thread;
    void *stack_start;
    /** 分配线程对象 */
    thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,
name);
    if (thread == RT_NULL)
        return RT_NULL;
    /** 分配线程的栈 */
    stack_start = (void *)RT_KERNEL_MALLOC(stack_size);
    if (stack_start == RT_NULL) {
        rt_object_delete((rt_object_t)thread);
        return RT_NULL;
    }
    /** 初始化线程实例 */
    _rt_thread_init(thread,
                    name,
                    entry,
                    parameter,
                    stack_start,
                    stack_size,
                    priority,
                    tick);
    return thread;
}

终于都调用到_rt_thread_init函数:
/******************************************************************************************* 
** 函数名称: _rt_thread_init
** 函数功能: 初始化线程实例
** 入口參数: thread 线程对象句柄
**    name 线程的名字
**    entry 线程的入口函数
**    parameter 附加參数
**    stack_start 栈底指针
**    stack_size 栈的大小
**    priority 线程的优先级
**    tick 线程的初始滴答数(能执行的时间片值)
** 返 回 值: 成功返回RT_EOK
** 调    用: rt_thread_init
*******************************************************************************************/
static 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_list_init(&(thread->tlist));
    thread->entry = (void *)entry;
    thread->parameter = parameter;
    thread->stack_addr = stack_start;
    thread->stack_size = (rt_uint16_t)stack_size;
    /** 初始化线程的栈 */
    rt_memset(thread->stack_addr, '#', thread->stack_size);
    thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
        (void *)((char *)thread->stack_addr + thread->stack_size - 4),
        (void *)rt_thread_exit);
    RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX);
    thread->init_priority    = priority;
    thread->current_priority = priority;
    thread->init_tick      = tick;
    thread->remaining_tick = tick;
    thread->error = RT_EOK;
 
    /** 创建线程时,线程处于INIT状态 */
    thread->stat  = RT_THREAD_INIT;
    thread->cleanup   = 0;
    thread->user_data = 0;
    /** 初始化线程内嵌的定时器 */
    rt_timer_init(&(thread->thread_timer),
                  thread->name,
                  rt_thread_timeout,
                  thread,
                  0,
                  RT_TIMER_FLAG_ONE_SHOT);
    return RT_EOK;
}
在这个函数中有几点须要注意:
1.线程的栈是怎样初始化的?
线程的栈是这样布局的:
-----------
| Entry   |        <--- 线程的入口函数
-----------    
|  LR     |        <--- 返回地址
-----------
|  R12    |        <--- 通用寄存器
-----------
|  R11    |
-----------
|  R10    |
-----------
|  R9     |
-----------
|  R8     |
-----------
|  R7     |
-----------
|  R6     |
-----------
|  R5     |
-----------
|  R4     |
-----------
|  R3     |
-----------
|  R2     |
-----------
|  R1     |
-----------
|  R0     |
-----------
|  CPSR   |    <--- 当前程序状态寄存器
-----------    
|  SPSR   |    <--- 保存程序状态寄存器
-----------

2.线程内嵌的定时器的目的?
线程内嵌定时器来实现线程状态的改变。比方当须要让线程休眠多少个时钟滴答时,能够将线程设置为挂起状态。然后设置定时器的超时时间启动定时器。这样当定时器超市就能唤醒线程

3.此时线程是否具备了执行条件?
初始化后线程的状态为INIT状态,并不能执行,要转换成就绪状态需调用rt_thread_startup


设置线程为就绪状态的接口函数有:rt_thread_control。rt_thread_resume。rt_thread_timeout
rt_thread_control
    rt_schedule_insert_thread
        thread->stat = RT_THREAD_READY

rt_thread_resume
    rt_schedule_insert_thread
        thread->stat = RT_THREAD_READY

rt_thread_timeout
    rt_schedule_insert_thread
        thread->stat = RT_THREAD_READY
能够发现设置线程为就绪状态的接口函数实际为rt_schedule_insert_thread
/*********************************************************************************************************
** 函数名称: rt_schedule_insert_thread
** 函数功能: 将线程插入到就绪队列中
** 入口參数: thread 线程对象句柄
** 返 回 值: 无
** 调    用:
*********************************************************************************************************/
void rt_schedule_insert_thread(struct rt_thread* thread)
{
    register rt_base_t temp;
    /** 參数检查 */
    RT_ASSERT(thread != RT_NULL);
    /** 禁止全局中断 */
    temp = rt_hw_interrupt_disable();
    /** 设置线程的状态为就绪态 */
    thread->stat = RT_THREAD_READY;
    /** 将线程插入到优先级队列中 */
    rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
                          &(thread->tlist));
#if RT_THREAD_PRIORITY_MAX <= 32
    RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,
("insert thread[%.*s], the priority: %d\n",
                                      RT_NAME_MAX, thread->name, thread->current_priority));
#else
    RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,
                 ("insert thread[%.*s], the priority: %d 0x%x %d\n",
                  RT_NAME_MAX,
                  thread->name,
                  thread->number,
                  thread->number_mask,
                  thread->high_mask));
#endif
    /** 设置就绪表和就绪组 */
#if RT_THREAD_PRIORITY_MAX > 32
    rt_thread_ready_table[thread->number]
|= thread->high_mask;
#endif
    rt_thread_ready_priority_group |=
thread->number_mask;
    /** 使能全局中断 */
    rt_hw_interrupt_enable(temp);
}
在函数中除了将线程设置为就绪状态外,还有几个动作须要关注:
1.将线程增加线程优先级链表中。在RT-Thread支持的优先级个数能够为32或256,但系统所支持的线程数目并没有限制。

因此,处于同一优先级的线程是能够多个的,这些线程将以链表连接起来。这些具有同样优先级的线程的调度方式为时间片调度。

rt_thread_priority_table[256]
----------
|   0    |----->线程2 ---> 线程5 --->...
----------
|   1    |
----------
.........
----------
|   253  | ---> 线程100 --->线程3
----------
|   254  |
----------
|   255  | ---> 线程50

----------


2.设置了全局的就绪表和就绪组


设置线程为挂起状态的接口函数有:rt_thread_startup,rt_thread_suspend

rt_thread_startup
    thread->stat = RT_THREAD_SUSPEND        /**
设置线程的状态为挂起状态 */

rt_thread_suspend
    thread->stat = RT_THREAD_SUSPEND
    rt_schedule_remove_thread

设置线程为挂起状态的接口函数有:rt_thread_exit。rt_thread_detach,rt_thread_delete
rt_thread_delete
    rt_schedule_remove_thread
    thread->stat = RT_THREAD_CLOSE
    rt_list_insert_after(&rt_thread_defunct,
&(thread->tlist))

rt_thread_detach
    rt_schedule_remove_thread
    rt_timer_detach
    thread->stat = RT_THREAD_CLOSE
    rt_object_detach

rt_thread_exit
    rt_schedule_remove_thread
    thread->stat = RT_THREAD_CLOSE
    rt_timer_detach

RT-Thread内核之线程调度(三)的更多相关文章

  1. STM32 + RT Thread OS 学习笔记[三]

    RTGUI 据说RTGUI是多线程的,因此与RT-Thread OS的耦合度较高,有可能要访问RT-Thread的线程控制块.如果要移植到其它OS,估计难度较大.目前还处于Alpha状态,最终将会包含 ...

  2. Linux内核设计第三周——构造一个简单的Linux系统

    Linux内核设计第三周 ——构造一个简单的Linux系统 一.知识点总结 计算机三个法宝: 存储程序计算机 函数调用堆栈 中断 操作系统两把宝剑: 中断上下文的切换 进程上下文的切换 linux内核 ...

  3. LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS

    LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163. ...

  4. Linux内核分析第三周学习笔记

    linux内核分析第三周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

  5. SQL Server的thread scheduling(线程调度)

      https://www.zhihu.com/question/53125711/answer/134461670 https://www.zhihu.com/question/53125711   ...

  6. Linux内核分析(三)----初识linux内存管理子系统

    原文:Linux内核分析(三)----初识linux内存管理子系统 Linux内核分析(三) 昨天我们对内核模块进行了简单的分析,今天为了让我们今后的分析没有太多障碍,我们今天先简单的分析一下linu ...

  7. 十天学Linux内核之第三天---内存管理方式

    原文:十天学Linux内核之第三天---内存管理方式 昨天分析的进程的代码让自己还在头昏目眩,脑子中这几天都是关于Linux内核的,对于自己出现的一些问题我会继续改正,希望和大家好好分享,共同进步.今 ...

  8. linux内核分析第三周

    20135103王海宁 linux内核分析第三周 http://mooc.study.163.com/course/USTC-1000029000  按照课堂提供的方法,命令行一行行敲上去,我是手机缓 ...

  9. 20135327郭皓--Linux内核分析第三周 构造一个简单的Linux系统MenuOS

    Linux内核分析第三周  构造一个简单的Linux系统MenuOS 前提回顾 1.计算机是如何工作的三个法宝 1.存储程序计算机 2.函数调用堆栈 3.中断 2.操作系统的两把宝剑 中断上下文的切换 ...

随机推荐

  1. matplotlib极坐标系应用之雷达图

    #!/usr/bin/env python3 #-*- coding:utf-8 -*- ############################ #File Name: test.py #Autho ...

  2. vue 过渡效果-列表过渡

    到目前为止,关于过渡我们已经讲到, 单个节点 同一时间渲染多个节点的一个 那么怎么同时渲染整个列表,比如使用v-if?在这种场景下,使用<transition-group>组件,在我们深入 ...

  3. Centos6.5 --配置 vsftp server

    事实上我这么懒得人是不想配置什么ftpserver的(毕竟动起来都认为麻烦).可是因为本菜鸟才刚開始步入linux的大坑.尽管有装Centos7的真机,可是因为一时还是脱离不了Windows平台,所以 ...

  4. C#调用C++dll文件 运行提示找不到函数的入口点

    1.首先用DllAnalyzer查看dll的输出函数名,发现输出的函数名有所变化,多了@xxx和一些别的奇怪的字符,实际上是因为C++重载机制造成的,使用使用extern "C"关 ...

  5. 线程同步工具CountDownLatch

    CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行.假如我们这个想要继续往下执行的任务调用一个CountDownLatc ...

  6. Chrome开发者工具之Network面板

    Chrome开发者工具面板 面板上包含了Elements面板.Console面板.Sources面板.Network面板. Timeline面板.Profiles面板.Application面板.Se ...

  7. linux远程控制windows

    我的开发环境是linux,但是需要同时维护windows和linux的服务器,所以有时需要在linux系统下也能远程控制windows的机器. rdesktop是一款开源的远程连接工具,它通过实现了R ...

  8. 从头认识java-17.4 具体解释同步(2)-具体解释竞争条件

    这一章节我们来具体讨论一下竞争条件. 1.为什么会引起竞争条件? 因为操作缺失原子性. 2.什么是原子性? 所谓原子操作是指不会被线程调度机制打断的操作:这样的操作一旦開始,就一直运行到结束.中间不会 ...

  9. db2 reorg pending

    通常在数据库上线之前,我们都会对数据库做周密的规划,无论在测试阶段还是上线之初,也难免由于需求的更改会对数据中的表做一些更改.而某些alter table语句则会导致该表处于reorg-pending ...

  10. 使用Lingo增强JMS

    虽然activemq+jencks的jms轻量级解决方案已经很好地在psa中work了,尤其spring的JmsTemplate使得代码更简单,但是还是存在问题. 问题来自暑期做psa的时候,link ...