• RTOS 的学习之创建线程


    1、定义线程栈

    在多线程系统中,每个线程都是独立的,互不干扰的,所以要为每个线程都分配独立的栈空间,每个栈空间通常是预先定义好的全局数组,也可以是动态分配的一段内存空间,但他们都存于RAM中。

      在多线程系统中,有多少个线程就需要定义多少个线程栈。

    1 ALIGN(RT_ALIGN_SIZE)// (2)
    2  /* 定义线程栈 */
    3 rt_uint8_t rt_flag1_thread_stack[512];// (1)
    4 rt_uint8_t rt_flag2_thread_stack[512];

    线程栈其实就是一个预先定义好的全局变量。在RT-Thread中,凡是涉及到数据类型的地方,RT-Thread 都会将标准的C数据类型用typedef重新取一个类型名,以“rt”前缀开头。这些经过重定义的数据类型放在rtdef.h。

    ALIGN是一个带参宏,设置变量需要多少个字节对齐,对在它下面的变量起作用。

    RT_ALIGN_SIZE 是一个在rtconfig.h中定义的宏,默认为4,表示4个字节对齐。

    2、定义线程函数

    线程是一个独立的函数,函数主体无限循环且不能返回。

    3、定义线程控制块

    在多线程系统中,线程的执行是由系统调度的。系统为了顺利的调度线程,为每个线程都额外定义了一个线程控制块,这个线程控制块就相当于线程的身份证,里面存有线程的所有消息,比如线程的栈指针,线程名称,线程的形参等。有了这个线程控制块之后,以后系统对线程的全部操作都可以通过这个线程控制块来实现。定义一个线程控制块需要一个新的数据类型,该数据类型在rtdef.h这个头文件中声明,使用它可以为每个线程都定义一个线程控制块实体。

    struct rt_thread// (1)
    { 
         void *sp; /* 线程栈指针 */
         void *entry; /* 线程入口地址 */
         void *parameter; /* 线程形参 */
         void *stack_addr; /* 线程起始地址 */
         rt_uint32_t stack_size; /* 线程栈大小,单位为字节 */
         rt_list_t tlist; /* 线程链表节点 */
     };
     typedef struct rt_thread *rt_thread_t;

    在RT-Thread中,都会给新声明的数据结构重新定义一个指针。往后如果要定义线程控制块变量就使用struct rt_thread xxx 的形式,定义线程控制块指针就使用rt_thread_t xxx 的形式。

    /* 定义线程控制块 */
    struct rt_thread rt_flag1_thread;
    struct rt_thread rt_flag2_thread;

    4、实现线程创建函数

    线程的栈,线程的函数实体,线程的控制块,最终需要联系起来才能由系统进行统一调度。那么这个联系的工作就由线程初始化函数rt_thread_init()来实现,该函数在thread.c中定义,在rtthread.h中声明,所有跟线程相关的函数都在这个文件定义。rt_thread_init()函数的实现:

    rt_err_t rt_thread_init(struct rt_thread *thread,           // (1) 
                                     void (*entry)(void *parameter), // (2)
                                     void *parameter,                       // (3)
                                     void *stack_start,                     // (4)
                                     rt_uint32_t stack_size)              // (5)
     { 
        rt_list_init(&(thread->tlist));                                  // (6)
        thread->entry = (void *)entry;                              // (7)
        thread->parameter = parameter;                          //  (8)
        thread->stack_addr = stack_start;                        // (9)
        thread->stack_size = stack_size;                         // (10)
    
     /* 初始化线程栈,并返回线程栈指针 */                         // (11)
         thread->sp = (void *)rt_hw_stack_init( thread->entry,
                             thread->parameter,
                             (void *)((char *)thread->stack_addr +thread->stack_size - 4) );
    
         return RT_EOK;                                                // (12)
     }                    

    遵循RT-Thread 中的函数命名规则,以小写的rt开头,表示这是一个外部函数,可以由用户调用,以_rt 开头的函数表示内部函数,只能由RT-Thread内部使用。紧接着是文件名,表示该函数放在那个文件,最后是函数功能名称。

    (1)thread 是线程控制块指针。

    (2)entry 是线程函数名,表示线程的入口。

    (3)parameter 是线程形参,用于传递线程参数。

    (4)stack_start 用于指向栈的起始地址。

    (5)stack_size 表示线程栈的大小,单位为字节。

  • 相关阅读:
    移植ssh到mini2440
    VMware中Ubuntu安装VMware Tools步骤及问题解决方法
    Linux的网卡由eth0变成了eth1,如何修复
    mini2440移植所有驱动到3.4.2内核详细解说
    单片机的一生(感觉在说大部分人)
    mini2440移植linux-3.4.2内核详细解说
    Ubuntu中恢复桌面的上下默认面板命令
    mini2440移植最新u-boot-2012.04.01详细解说
    MyEclipse CI 2018.8.0 官方最新免费版(破解文件+激活工具+破解教程)
    cocos 获取一个骨骼动画多次显示播放
  • 原文地址:https://www.cnblogs.com/tansuoxinweilai/p/14947710.html
Copyright © 2020-2023  润新知