HarmonyOS鸿蒙Next内核源码分析(线程概念篇) | 是谁在不停的折腾CPU? | 中文注解HarmonyOS源码 | v21.03

HarmonyOS鸿蒙Next内核源码分析(线程概念篇) | 是谁在不停的折腾CPU? | 中文注解HarmonyOS源码 | v21.03

本篇说清楚任务的问题

在鸿蒙内核线程(thread)就是任务(task),也可以叫作业.线程是对外的说法,对内就叫任务.跟王二毛一样, 在公司叫你王董,回到家里还有领导,就叫二毛啊.这多亲切.在鸿蒙内核是大量的task,很少看到thread,只出现在posix层.当一个东西理解就行.

读本篇之前建议先鸿蒙内核源码分析(总目录)

调度故事篇,里面有对任务生活场景式的比喻. 鸿蒙内核源码分析定位为深挖内核地基,构筑底层网图.就要见真身,剖真人.任务(LosTaskCB)原始真身如下,本篇一一剖析它,看看它的五脏六腑里到底是个啥.

第一大块:多核CPU相关块

#if (LOSCFG_KERNEL_SMP == YES) //多CPU核支持
    UINT16 currCpu; //正在运行此任务的CPU内核号
    UINT16 lastCpu; //上次运行此任务的CPU内核号
    UINT16 cpuAffiMask; //CPU亲和力掩码,最多支持16核,亲和力很重要,多核情况下尽量一个任务在一个CPU核上运行,提高效率
    UINT32 timerCpu; //此任务的CPU内核号被延迟或挂起
#if (LOSCFG_KERNEL_SMP_TASK_SYNC == YES)
    UINT32 syncSignal; //用于CPU之间 同步信号
#endif
#if (LOSCFG_KERNEL_SMP_LOCKDEP == YES) //死锁检测开关
    LockDep lockDep;
#endif
#if (LOSCFG_KERNEL_SCHED_STATISTICS == YES) //调度统计开关,显然打开这个开关性能会受到影响,鸿蒙默认是关闭的
    SchedStat schedStat; //调度统计
#endif
#endif

鸿蒙内核支持多CPU,谁都知道多CPU当然好,效率高,快嘛,但凡事有两面性,在享受一个东西带来好处的同时,也得承担伴随它一起带来的麻烦和风险.多核有哪些的好处和麻烦,这里不展开说,后续有专门的文章和视频说明.任务可叫线程,或叫作业.CPU就是做作业的,多个CPU就是有多个能做作业的,一个作业能一鼓作气做完吗?

答案是:往往不行,因为现实不允许,作业可以有N多,而CPU数量非常有限,所以经常做着A作业被老板打断让去做B作业.这老板就是调度算法.A作业被打断回来接着做的还会是原来那个CPU吗?

答案是:不一定. 变量cpuAffiMask叫CPU亲和力,它的作用是可以指定A的作业始终是同一个CPU来完成, 也可以随便,交给调度算法,分到谁就谁来,这方面可以不挑.

第二大块:栈空间

VOID *stackPointer; //非用户模式下的栈指针
UINT32 stackSize; //非用户模式下栈大小
UINTPTR topOfStack; //非用户模式下的栈顶 bottom = top + size

UINTPTR userArea; //使用区域,由运行时划定,根据运行态不同而不同
UINTPTR userMapBase; //用户模式下的栈底位置
UINT32 userMapSize; //user thread stack size ,real size : userMapSize + USER_STACK_MIN_SIZE

关于栈空间看过很多文章说每个任务都有自己独立的用户栈空间和内核栈空间,其实这种说法不严谨,至少在鸿蒙内核不能这么去理解,否则会有很多疑惑,解释不通的.

CPU做作业就需要场地,栈空间就是给CPU做作业的场地.公司(内核设计者)规定用户的作业由用户提供场地, 用户场地就叫用户栈空间,但有些作业比较敏感不方便在用户现场完成,需要回到公司指定场地做,公司的场地就叫内核栈空间.

所以准确的说法是每个任务都有自己独立的用户栈空间和共用一个内核栈空间.每个CPU在公司都有自己独立的办公位,不可能每个用户作业在公司内部有对应办公位的,明显的浪费内核资源,行不通的.而那些敏感作业就叫系统调用.

第三大块:资源竞争/同步

VOID *taskSem; //task在等哪个信号量
VOID *taskMux; //task在等哪把锁
VOID *taskEvent; //task在等哪个事件
UINT32 eventMask; //事件屏蔽
UINT32 eventMode; //事件模式
FutexNode futex; //实现快锁功能
LOS_DL_LIST joinList; //联结链表,允许任务之间相互释放彼此
LOS_DL_LIST lockList; //拿到了哪些锁链表
UINT32 signal; //任务信号类型,(SIGNAL_NONE,SIGNAL_KILL,SIGNAL_SUSPEND,SIGNAL_AFFI)
sig_cb sig;

公司的资源是有限的,CPU自己也是公司的资源,除了它还有其他的设备,比如做作业用的黑板,用户A,B,C都可能用到,狼多肉少,咋搞?

互斥量(taskMux,futex)能解决这个问题,办事前先拿锁,拿到了锁的爽了,没有拿到的就需要排队,在lockList上排队,注意lockList是个双向链表,它是内核最重要的结构体,开篇就提过,没印象的看这篇 鸿蒙内核源码分析(双向链表篇) | 谁是内核最重要结构体?,上面挂都是等锁进房间的西门大官人.这是互斥量的原理,解决任务间资源紧张的竞争性问题.

另外一个是用于任务的同步的信号(sig_cb),任务和任务之间是会有关联的,现实生活中公司的A,B用户之间本身有业务往来的正常,CPU在帮B做作业的时候发现前置条件是需要A完成某项作业才能进行,这时B就需要主动让出CPU先办完A的事.这就是信号量的原理,解决的是任务间的同步问题.

第四大块:任务调度

UINT16 taskStatus; //各种状态标签,可以拥有多种标签,按位标识
UINT16 priority; //任务优先级[0:31],默认是31级
UINT16 policy; //任务的调度方式(三种 .. LOS_SCHED_RR)
UINT16 timeSlice; //剩余时间片
CHAR taskName[OS_TCB_NAME_LEN]; //任务的名称
LOS_DL_LIST pendList; //如果任务阻塞时就通过它挂到各种阻塞情况的链表上,比如OsTaskWait时
LOS_DL_LIST threadList; //挂到所属进程的线程链表上
SortLinkList sortList; //挂到cpu core 的任务执行链表上

是简单的先来后到(FIFO)吗? 当然也支持这个方式.鸿蒙内核用的是抢占式调度(policy),就是可以插队,比优先级(priority)大小,[0,31]级,数字越大的优先级越低,跟考试一样,排第一才是最牛的.

鸿蒙排0的最牛! 想也想得到内核的任务优先级都是很高的,比如资源回收任务排第5,定时器任务排第0.够牛了吧.普通老百姓排多少呢?默认28级,惨!!!

另外任务有时间限制timeSlice,叫时间片,默认20ms,用完了会给你重置,发起重新调度,找出优先级高的执行,阻塞的任务(比如没拿到锁的,等信号量同步的,等读写消息队列的)都挂到pendList上,方便管理.

第五大块:任务间通讯

#if (LOSCFG_KERNEL_LITEIPC == YES)
    UINT32 ipcStatus; //IPC状态
    LOS_DL_LIST msgListHead; //消息队列头结点,上面挂的都是任务要读的消息
    BOOL accessMap[LOSCFG_BASE_CORE_TSK_LIMIT]; //访问图,指的是task之间是否能访问的标识,LOSCFG_BASE_CORE_TSK_LIMIT 为任务池总数
#endif

这个很重要,解决任务间通讯问题,要知道进程负责的是资源的管理功能,什么意思?就是它不并负责内容的生产和消费,它只负责管理确保你的内容到达率和完整性.生产者和消费者始终是任务.进程管了哪些东西系列篇有专门的文章,请自行翻看.

liteipc是鸿蒙专有的通讯消息队列实现.简单说它是基于文件的,而传统的ipc消息队列是基于内存的.有什么区别也不在这里讨论,已有专门的文章分析.

第六大块:辅助工具

#if (LOSCFG_KERNEL_SMP_LOCKDEP == YES) //死锁检测开关
    LockDep lockDep;
#endif
#if (LOSCFG_KERNEL_SCHED_STATISTICS == YES) //调度统计开关,显然打开这个开关性能会受到影响,鸿蒙默认是关闭的
    SchedStat schedStat; //调度统计
#endif

以上就是任务的五脏六腑,看清楚它鸿蒙内核的影像会清晰很多!


喜欢就大方 点赞+关注+收藏 吧

各大站点搜 “鸿蒙内核源码分析”,快速找到组织.

10 回复

拜读了,挺不错

更多关于HarmonyOS鸿蒙Next内核源码分析(线程概念篇) | 是谁在不停的折腾CPU? | 中文注解HarmonyOS源码 | v21.03的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


喜欢这样的有深度的内容

这么硬核,没谁了

很喜欢HarmonyOS的卡片式设计,信息一目了然,操作也更便捷。

我也要跟着一起学习啊,哈哈

这么棒,优秀

支持,写的走心,棒棒哒

感谢你的分享

在HarmonyOS鸿蒙Next内核中,线程是操作系统调度的基本单位,负责执行任务。线程通过抢占式调度机制,轮流使用CPU资源。鸿蒙Next内核采用轻量级线程设计,支持多任务并发执行。线程的创建、调度和销毁由内核管理,确保系统资源的高效利用。

线程的状态包括就绪、运行、阻塞和终止。内核通过线程控制块(TCB)管理线程信息,如栈指针、寄存器状态等。线程调度器根据优先级和调度策略分配CPU时间片,确保高优先级任务优先执行。

鸿蒙Next内核支持线程间的同步与通信,提供信号量、互斥锁等机制,防止资源竞争。线程调度器通过时间片轮转和优先级抢占,确保系统响应性和实时性。

源码中的线程相关函数包括线程创建、调度、同步和销毁等操作。通过分析源码,可以深入理解鸿蒙Next内核的线程管理机制和调度策略。

在HarmonyOS鸿蒙Next内核中,线程是CPU调度的基本单位。内核通过线程管理实现多任务并发执行。线程的创建、调度和销毁由内核负责,确保CPU资源的高效利用。源码中,线程相关的数据结构如TaskControlBlock(任务控制块)记录了线程的状态、优先级等信息。调度器根据这些信息决定哪个线程获得CPU使用权。通过分析源码,可以深入理解鸿蒙系统如何通过线程管理实现高效的任务调度和资源分配。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!