• 具体应用中,线程总数 不受 限制,能创建 的 线程总数 只和 具体 硬件平台 的 内存 有关

    • 创建线程 的时候 需要 设置 线程栈大小
  • 线程优先级 和 线程时间片

    • 线程优先级

      • 优先级 描述了 线程 竞争 处理器资源 的 能力
      • RT-Thread 最大支持 256 个优先级(数值越小的优先级越高,0 为最高优先级, 最低优先级 预留给 空闲线程)(空闲线程后面会讲到)
      • 用户可以通过 rt_config.h 中的 RT_THREAD_PRIORITY_MAX 宏 来 修改 最大支持 的 优先级
        • target\rtconfig.h

          /* PRIORITY_MAX */
          #define RT_THREAD_PRIORITY_MAX	32
          
    • 线程时间片

      • 时间片 只有在 相同优先级 的 就绪态线程 中 起作用,系统对 优先级相同 的 就绪态线程 采用 时间片轮转 的 调度方式 进行 调度 时,时间片 起到 约束线程 单次运行时长 的 作用

      • 其单位是一个系统节拍(OS Tick)

      • 假设有 2个优先级相同 的 就绪态线程 A 与 B,A线程 的 时间片 设置为 10,B线程 的 时间片 设置为 5

      • 那么当 系统中 不存在 比 A优先级 高的 就绪态线程 时,系统会在A、B线程间来回切换执行,并且每次对A线程执行10个节拍的时长,对B线程执行5个节拍的时长

        image.png

  • 线程调度规则

    • 优先级抢占调度
      • 操作系统总是让具有最高优先级的就绪任务优先运行:即当有任务的优先级高于当前任务优先级并且处于就绪态后,就一定会发生任务调度
      • 通过优先级抢占机制,最大限度的满足了系统的实时性
    • 时间片轮询调度
      • 当操作系统中存在相同优先级的线程时(优先级相同就不会抢占),操作系统会按照设置的时间片大小来轮流调度线程,时间片起到约束线程单次运行时长的作用,其单位是一个系统节拍(OS Tick)
      • 通过时间片轮询,保证优先级相同的任务能够轮流占有处理器
  • 时间片轮询调度示例

    /* 线程入口 */
    static void thread_entry(void* parameter)
    {
        rt_uint32_t value;
        rt_uint32_t count = 0;
    
        value = (rt_uint32_t)parameter;
        while (1)
        {
            if(0 == (count % 5))
            {           
                rt_kprintf("thread %d is running ,thread %d count = %d\\n", value , value , count);      
    
                if(count > 200)
                    return;            
            }
             count++;
         }  
    }
    
    int timeslice_sample(void)
    {
        rt_thread_t tid;
        /* 创建线程1 */
        tid = rt_thread_create("thread1", 
                                thread_entry, 		// thread1 线程入口函数 (时间片=10)
    														(void*)1, 				// thread1 的 parameter 是 1
                                THREAD_STACK_SIZE, 
                                THREAD_PRIORITY, 
    														THREAD_TIMESLICE);
        if (tid != RT_NULL) 
            rt_thread_startup(tid);
    
        /* 创建线程2 */
        tid = rt_thread_create("thread2", 
                                thread_entry, 		// thread2 线程入口函数 (时间片=5)
    														(void*)2,					// thread2 的 parameter 是 2
                                THREAD_STACK_SIZE, 
                                THREAD_PRIORITY, 
    														THREAD_TIMESLICE-5);
        if (tid != RT_NULL) 
            rt_thread_startup(tid);
        return 0;
    }
    
    /* 导出到 msh 命令列表中 */
    MSH_CMD_EXPORT(timeslice_sample, timeslice sample);