线程?它是啥?编程
在咱们刚开始进入嵌入式软件的编程领域时,每次都会接触到一个函数——main函数,在裸机的编程中,程序的执行流程就是在main函数中进行的,main函数也能够理解为一个线程,它也有它的栈空间来存储变量。可是,若是有许多线程呢,怎样来区分它们?又怎样来分配存储空间?数组
对于这个问题,RTThread有它的解决办法。多线程
首先是线程栈app
栈,是一种经典的储存结构,RTThread为每一个线程都分配了栈空间,来看看它是怎样定义的。函数
ALIGN(RT_ALIGN_SIZE) //线程栈对齐 static rt_uint8_t rt_led1_thread_stack[1024]; //定义线程栈
这是一个rt_uint8_t(RTThread中的宏定义,无符号8位)类型的全局数组,第一句话是为了栈空间对齐,使得CPU对数据的访问更加高效,第二句就是线程的具体定义了,这里定义1024的长度。ui
而后是线程的ID卡——线程控制块this
在操做系统中,经常有许多的线程在运行,面对着这么多的的线程,天然须要一个身份块来标识每一个线程,使得系统便于管理。而这个身份,就是线程控制块。spa
具体定义以下:操作系统
struct rt_thread { /* rt object */ char name[RT_NAME_MAX]; /**< the name of thread */ rt_uint8_t type; /**< type of object */ rt_uint8_t flags; /**< thread's flags */ #ifdef RT_USING_MODULE void *module_id; /**< id of application module */ #endif rt_list_t list; /**< the object list */ rt_list_t tlist; /**< the thread list */ /* stack point and entry */ void *sp; /**< stack point */ void *entry; /**< entry */ void *parameter; /**< parameter */ void *stack_addr; /**< stack address */ rt_uint32_t stack_size; /**< stack size */ /* error code */ rt_err_t error; /**< error code */ rt_uint8_t stat; /**< thread status */ /* priority */ rt_uint8_t current_priority; /**< current priority */ rt_uint8_t init_priority; /**< initialized priority */ #if RT_THREAD_PRIORITY_MAX > 32 rt_uint8_t number; rt_uint8_t high_mask; #endif rt_uint32_t number_mask; #if defined(RT_USING_EVENT) /* thread event */ rt_uint32_t event_set; rt_uint8_t event_info; #endif #if defined(RT_USING_SIGNALS) rt_sigset_t sig_pending; /**< the pending signals */ rt_sigset_t sig_mask; /**< the mask bits of signal */ void *sig_ret; /**< the return stack pointer from signal */ rt_sighandler_t *sig_vectors; /**< vectors of signal handler */ void *si_list; /**< the signal infor list */ #endif rt_ubase_t init_tick; /**< thread's initialized tick */ rt_ubase_t remaining_tick; /**< remaining tick */ struct rt_timer thread_timer; /**< built-in thread timer */ void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit */ /* light weight process if present */ #ifdef RT_USING_LWP void *lwp; #endif rt_uint32_t user_data; /**< private user data beyond this thread */ };
看起来线程控制块的定义很是复杂,实际上,线程控制块的主要包含信息有对象成员相关(RTT(hread)经过对象来进行管理),线程链表相关(RTT经过线程链表实现调度,也被称为优先级表/就绪链表),线程栈相关和线程自己的相关地址。使用时,须要经过static struct定义一个控制块结构体线程
初始化:
线程初始化定义以下:
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)
初始化的须要的参数有(从上到下):线程控制块地址,线程名称,入口函数地址,入口函数参数,栈起始地址,线程优先级和线程时间片。使用时,需引入具体参数。
具体定义:
线程的具体定义,给出一个荔枝(这里部分参考了野火哥的例程):
static void led_thread_entry(void *parameter) { while(1) { LED_ON; rt_thread_mdelay(1000); LED_OFF; rt_thread_mdelay(1000); } }
须要特别注意的是,这里必定要用RTT系统的延时,不然线程不会让出CPU供其余线程使用,这就不是一个RTOS系统了。
启动线程,开始调度:
万事俱备,只欠东风,只须要启动线程(参数为线程控制块地址):
rt_thread_startup(&ABCDEFG);
便可纵享RTOS系统的魅力。
(因为我的水平有限,可能会出现理解,语句错误,请注意~:)