rt-thread 线程知识

线程是操作系统的一个重要概念,正是因为有了线程,操作系统才可以实现多任务。在了解线程之前,先来看一下在没有操作系统之前实现多任务是怎样的。
所谓的多任务就是让MCU能够在宏观上同时运行多个函数,在没有使用操作系统的时候,实现多任务通常是利用定时器判断标志位,然后在主函数中根据标志位来选择不同的函数执行。但是这种方法的实时性很差,并且不能自由地控制函数的执行,停止。

int flag = 0;
void main(void)
{
	while(1)
	{	
		switch(flag)
		{
			case 1:
				task1();
			break;
			case 2:
				task2();
			break;
			case 3:
				task3();
			break;
		}
	}

}

void timer_handler(void)
{
	static int count = 0;
	count++;
	if(count <= 50)
	{
		flag = 1;
	}
	else if(count > 50 && count <= 100)
	{
		flag = 2;
	}
	else if(count > 100 && count <= 150)
	{
		flag = 3;
	}
	else
	{
		count = 0;
	}

}

在rt-thread中利用线程来实现多任务功能,线程是rt-thread操作系统中的一个很重要的概念,在rt-thread中线程有有两种,分别是系统线程和用户线程,系统线程由rt-thread操作系统创建,主要用于管理内核的一些资源。而用户线程由用户自己创建。

  • 线程控制块
    rt-thread为了更好的对线程进行控制,定义了一个叫线程控制块的数据结构,把线程的所有属性都包含在里面,线程控制块中的一些重要参数都已经做了注释。
struct rt_thread
{
    /* rt object */
    char        name[RT_NAME_MAX];                     //线程名字
    rt_uint8_t  type;                                   //对象类型
    rt_uint8_t  flags;                                  //标志位

#ifdef RT_USING_MODULE
    void       *module_id;                              /**< id of application module */
#endif

    rt_list_t   list;                                   //对象链表
    rt_list_t   tlist;                                 //线程链表

    /* stack point and entry */
    void       *sp;                                    //栈指针
    void       *entry;                                  //入口函数
    void       *parameter;                             //线程参数
    void       *stack_addr;                             //栈起始地址
    rt_uint32_t stack_size;                             //栈大小

    /* error code */
    rt_err_t    error;                                  //错误码

    rt_uint8_t  stat;                                   //线程状态

#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;                       //线程优先级
    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 */

#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 */

    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;                             //用户私有数据
};
  • 线程优先级
    rt-thread中可以设置线程优先级,优先级高的线程可以抢占优先级低的线程。rt-thread中支持的优先级为256级(0-255),其中优先级数字越小,优先级越高。不同的MCU可以根据实际情况修改最大优先级,默认最低的优先级给空闲进程使用,用户可以根据线程的功能自行选择优先级。
  • 线程状态
    rt-thread中线程拥有不同的状态,有运行态,睡眠态,就绪态等
    初始态:线程创建完成,但是并没有运行,不参与调度,此时线程状态为初始态RT_THREAD_INIT。
    就绪态:线程被放到就绪队列中等待调度器调度,此时线程状态为RT_THREAD_READY。
    运行态:线程获得CPU和外部资源并开始运行,此时线程状态为运行态RT_THREAD_RUNNING。
    挂起态:挂起态也叫阻塞态,线程在等待某些资源,比如信号量,互斥量,事件,消息等,也可以是线程调用睡眠延时函数,此时线程状态为挂起态RT_THREAD_SUSPEND。
    关闭态:线程退出运行,不参与调度,此时线程为关闭态RT_THREAD_CLOSE。
  • 线程时间片

在实时操作系统中,每个线程都有自己的时间片,所谓时间片就是线程一次可以运行多长事件。时间片仅对优先级相同的线程有用,当线程优先级相同时,会采用时间片轮转调度的方式进行线程的调度。每个线程都安装规定的时间片运行,当时间片到的时候,线程就会让出CPU,给下一个进程运行,如此循环所有优先级相同的进程。

  • 线程入口函数
    在创建线程时都会有一个线程入口函数,这个函数就是用户自定义的函数。
void thread_entry(void* paramenter)
{
	while (1)
	{
		/* 等 待 事 件 的 发 生 */
		/* 对 事 件 进 行 服 务、 进 行 处 理 */
	}
}

通过会在线程函数中循环做一些事情,但是这里需要注意一点是,不要让线程函数陷入死循环。在优先级相同的线程中,可以让线程陷入死循环,因为优先级相同会采用时间片调度的方法依次运行。但是当高优先级线程陷入死循环时,会导致低优先级的线程无法执行。所以在线程中要有让出CPU的行为。

  • 线程错误码
    在线程的生命周期中,可能会出现各种的意想不到的错误,rt-thread中为线程定义了一系列的错误代码,并将线程错误记录在线程控制块中。
#define RT_EOK                          0               /**< There is no error */
#define RT_ERROR                        1               /**< A generic error happens */
#define RT_ETIMEOUT                     2               /**< Timed out */
#define RT_EFULL                        3               /**< The resource is full */
#define RT_EEMPTY                       4               /**< The resource is empty */
#define RT_ENOMEM                       5               /**< No memory */
#define RT_ENOSYS                       6               /**< No system */
#define RT_EBUSY                        7               /**< Busy */
#define RT_EIO                          8               /**< IO error */
#define RT_EINTR                        9               /**< Interrupted system call */
#define RT_EINVAL                       10              /**< Invalid argument */
  • 线程栈
    每个线程都有自己独立的线程栈,线程栈在线程创建的时候被分配。当线程需要被切换的时候,会将线程的一些信息保存在线程栈中,当线程恢复的时候会从线程栈中恢复线程信息,同时线程栈也用来保存线程定义的局部变量。
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RT-Thread 是一个实时操作系统,支持多线程操作。线程是 RT-Thread 中的基本执行单元,可以通过 RT-Thread 的 API 来创建和管理线程。 RT-Thread 线程创建 API 主要有以下几个: 1. rt_thread_t rt_thread_create(const char *name, void (*entry)(void *parameter), void *parameter, size_t stack_size, rt_uint8_t priority, rt_uint32_t tick); 该函数用于创建一个线程,参数如下: - name:线程的名称(必填)。 - entry:线程的入口函数(必填)。 - parameter:传递给线程入口函数的参数。 - stack_size:线程栈的大小,以字节为单位。 - priority:线程的优先级,取值范围是 0~31,数值越小优先级越高。 - tick:线程的时间片长度,以系统时钟节拍为单位。 2. void rt_thread_startup(rt_thread_t thread); 该函数用于启动一个线程,参数是线程句柄。 3. rt_thread_t rt_thread_self(void); 该函数返回当前线程的句柄。 4. rt_err_t rt_thread_delete(rt_thread_t thread); 该函数用于删除一个线程,参数是线程句柄。 5. rt_err_t rt_thread_yield(void); 该函数用于让出当前线程的时间片,让其他线程执行。 6. rt_err_t rt_thread_suspend(rt_thread_t thread); 该函数用于挂起一个线程,使其暂停执行。 7. rt_err_t rt_thread_resume(rt_thread_t thread); 该函数用于恢复一个被挂起的线程,使其继续执行。 以上是 RT-Thread 线程创建的几个基本 API,可以根据实际需求选择使用。需要注意的是,线程的优先级和时间片长度是影响线程执行顺序的重要因素,需要根据实际情况进行设置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值