赞
踩
在裸机系统开发中,系统的主体就是在main函数里面顺序执行的无限循环,在这个无限循环中,CPU按照顺序完成各种操作。在多线程系统中,根据功能的不同,把整个系统分割成一个个独立的且无法返回的函数,这个函数就成为线程,也可以称其为任务。
栈是单片机RAM里的一段连续的内存空间,栈的大小一般在启动文件或者链接脚本中指定,最后由C库函数__main进行初始化。
在多线程系统中,每个线程都是独立的、互不干扰的,所以要为每个线程都分配独立的栈空间。这个栈空间通常是一个预先定义好的全局数组,也可以是动态分配的一段内存空间。无论是哪种情况,栈空间都存在于RAM中。
定义线程栈的示例代码如下:
- ALIGN(RT_ALIGN_SIZE)
-
- rt_uint8_t thread1_stack[512];
- rt_uint8_t thread2_stack[1024];
线程是一个独立的函数,函数主体无限循环且不能返回。如下代码所示:
- void thread1_entry(void *arg)
- {
- while(1)
- {
- flag1 = 1;
- delay(100);
- flag1 = 0;
- delay(100);
- }
- }
-
- void thread2_entry(void *arg)
- {
- while(1)
- {
- flag2 = 0;
- delay(100);
- flag2 = 1;
- delay(100);
- }
- }
在裸机系统中,程序的主体是CPU按照顺序执行的;而在多线程系统中,线程的执行则是由系统调度的。系统为了顺利地调度线程,会为每个线程单独定义一个线程控制块,这个线程控制块相当于线程的“身份证”,里边存有线程的所有信息。有了线程控制块这个“identifier”,系统以后对线程的全部操作都由其来实现。线程控制块在rtdef.h中声明,使用它可以为每个线程都定义一个线程控制块实体,代码如下所示:
- /**
- * Thread structure
- */
- 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 */
-
- #ifdef RT_USING_SMP
- rt_uint8_t bind_cpu; /**< thread is bind to cpu */
- rt_uint8_t oncpu; /**< process on cpu */
-
- rt_uint16_t scheduler_lock_nest; /**< scheduler lock count */
- rt_uint16_t cpus_lock_nest; /**< cpus lock count */
- rt_uint16_t critical_lock_nest; /**< critical lock count */
- #endif /*RT_USING_SMP*/
-
- /* priority */
- rt_uint8_t current_priority; /**< current 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 */
-
- #ifndef RT_USING_SMP
- void *sig_ret; /**< the return stack pointer from signal */
- #endif
- 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 */
-
- #ifdef RT_USING_CPU_USAGE
- rt_uint64_t duration_tick; /**< cpu usage tick */
- #endif
-
- 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_ubase_t user_data; /**< private user data beyond this thread */
- };
- typedef struct rt_thread *rt_thread_t;
定义线程控制块的代码如下所示:
- struct rt_thread thread1;
- struct rt_thread thread2;
线程的栈、函数实体和线程控制块最终需要联系起来才能由系统进行统一调度,这个联系的工作就由线程初始化函数rt_thread_init函数来实现。rt_thread_init函数在thread.c(src\thread.c)中实现,在thread.h(include\rtthread.h)中声明。函数实现代码如下所示:
- static rt_err_t _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)
- {
- /* init thread list */
- rt_list_init(&(thread->tlist));
-
- thread->entry = (void *)entry;
- thread->parameter = parameter;
-
- /* stack init */
- thread->stack_addr = stack_start;
- thread->stack_size = stack_size;
-
- /* init thread stack */
- rt_memset(thread->stack_addr, '#', thread->stack_size);
- #ifdef ARCH_CPU_STACK_GROWS_UPWARD
- thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
- (void *)((char *)thread->stack_addr),
- (void *)_thread_exit);
- #else
- thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
- (rt_uint8_t *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)),
- (void *)_thread_exit);
- #endif /* ARCH_CPU_STACK_GROWS_UPWARD */
-
- /* priority init */
- RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX);
- thread->current_priority = priority;
-
- thread->number_mask = 0;
-
- #ifdef RT_USING_EVENT
- thread->event_set = 0;
- thread->event_info = 0;
- #endif
-
- #if RT_THREAD_PRIORITY_MAX > 32
- thread->number = 0;
- thread->high_mask = 0;
- #endif /* RT_THREAD_PRIORITY_MAX > 32 */
-
- /* tick init */
- thread->init_tick = tick;
- thread->remaining_tick = tick;
-
- /* error and flags */
- thread->error = RT_EOK;
- thread->stat = RT_THREAD_INIT;
-
- #ifdef RT_USING_SMP
- /* not bind on any cpu */
- thread->bind_cpu = RT_CPUS_NR;
- thread->oncpu = RT_CPU_DETACHED;
-
- /* lock init */
- thread->scheduler_lock_nest = 0;
- thread->cpus_lock_nest = 0;
- thread->critical_lock_nest = 0;
- #endif /* RT_USING_SMP */
-
- /* initialize cleanup function and user data */
- thread->cleanup = 0;
- thread->user_data = 0;
-
- /* initialize thread timer */
- rt_timer_init(&(thread->thread_timer),
- thread->name,
- _thread_timeout,
- thread,
- 0,
- RT_TIMER_FLAG_ONE_SHOT);
-
- /* initialize signal */
- #ifdef RT_USING_SIGNALS
- thread->sig_mask = 0x00;
- thread->sig_pending = 0x00;
-
- #ifndef RT_USING_SMP
- thread->sig_ret = RT_NULL;
- #endif /* RT_USING_SMP */
- thread->sig_vectors = RT_NULL;
- thread->si_list = RT_NULL;
- #endif /* RT_USING_SIGNALS */
-
- #ifdef RT_USING_LWP
- thread->lwp = RT_NULL;
- #endif /* RT_USING_LWP */
-
- #ifdef RT_USING_CPU_USAGE
- thread->duration_tick = 0;
- #endif
-
-
- #ifdef RT_USING_MODULE
- thread->module_id = 0;
- #endif
-
- thread->user_data = 0;
-
- RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread));
-
- return RT_EOK;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。