大奖18dj18vip-大奖18dj18娱乐官网

大奖18dj18vip

 找回密码
 注册
查看: 155|回复: 0
打印 上一主题 下一主题

鸿蒙内核源码分析(双向链表篇) | 最重要结构体

[复制链接]

超级钻石贵宾会员

1万

主题

2万

帖子

6万

积分

Rank: 1

UID
15343
威望
-561
贡献
8107
在线时间
384 小时
注册时间
2015-10-12
跳转到指定楼层
楼主
发表于 2021-1-22 14:29:32 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

想了解更多内容,请访问:

51CTO和华为官方战略合作共建的鸿蒙技术社区

http://harmonyos.51cto.com/#zz

鸿蒙内核源码注释中文版 < Gitee仓 | CSDN仓 | Github仓 | Coding仓 >精读内核源码,中文注解分析,深挖地基工程,构建底层网图,四大码仓每日同步更新。

鸿蒙源码分析系列篇 < CSDN | OSCHINA | WeHarmony | 公众号 >问答式导读,生活式比喻,表格化说明,图形化展示,主流站点每日同步更新。

谁是鸿蒙内核最重要的结构体?

答案一定是: LOS_DL_LIST(双向链表),它长这样。

  • typedef struct LOS_DL_LIST {//双向链表,内核最重要结构体
  •     struct LOS_DL_LIST *pstPrev; /**< Current node's pointer to the previous node *///前驱节点(左手)
  •     struct LOS_DL_LIST *pstNext; /**< Current node's pointer to the next node *///后继节点(右手)
  • } LOS_DL_LIST;

结构体够简单了吧,只有前后两个指向自己的指针,但恰恰是因为太简单,所以才太不简单. 就像氢原子一样,宇宙中无处不在,占比最高,原因是因为它最简单,最稳定!

内核的各自模块都能看到双向链表的身影,下图是各处初始化双向链表的操作,因为太多了,只截取了部分:


很多人问图怎么来的, source insight 4.0 是阅读大型C/C++工程的必备工具,要用4.0否则中文有乱码。

可以豪不夸张的说理解LOS_DL_LIST及相关函数是读懂鸿蒙内核的关键。前后指针(注者后续将比喻成一对左右触手)灵活的指挥着系统精准的运行,越是深入分析内核源码,越能感受到内核开发者对LOS_DL_LIST非凡的驾驭能力,笔者仿佛看到了无数双手前后相连,拉起了一个个双向循环链表,把指针的高效能运用到了极致,这也许就是编程的艺术吧!这么重要的结构体还是需详细讲解一下。

基本概念

双向链表是指含有往前和往后两个方向的链表,即每个结点中除存放下一个节点指针外,还增加一个指向其前一个节点的指针。其头指针head是唯一确定的。从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点,这种数据结构形式使得双向链表在查找时更加方便,特别是大量数据的遍历。由于双向链表具有对称性,能方便地完成各种插入、删除等操作,但需要注意前后方向的操作。

功能接口

鸿蒙系统中的双向链表模块为用户提供下面几个接口。

请结合下面的代码和图去理解双向链表,不管花多少时间,一定要理解它的插入/删除动作, 否则后续内容将无从谈起.

  • //将指定节点初始化为双向链表节点
  • LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
  • {
  •     list->pstNext = list;
  •     list->pstPrev = list;
  • }
  • //将指定节点挂到双向链表头部
  • LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_LIST *node)
  • {
  •     node->pstNext = list->pstNext;
  •     node->pstPrev = list;
  •     list->pstNext->pstPrev = node;
  •     list->pstNext = node;
  • }
  • //将指定节点从链表中删除,自己把自己摘掉
  • LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
  • {
  •     node->pstNext->pstPrev = node->pstPrev;
  •     node->pstPrev->pstNext = node->pstNext;
  •     node->pstNext = NULL;
  •     node->pstPrev = NULL;
  • }

具体用法

举例 ProcessCB(进程控制块)是描述一个进程的所有信息,其中用到了 8个双向链表,这简直比章鱼还牛逼,章鱼也才四双触手,但进程有8双(16只)触手。

  • typedef struct ProcessCB {
  •     LOS_DL_LIST          pendList;                     /**< Block list to which the process belongs */ //进程所属的阻塞列表,如果因拿锁失败,就由此节点挂到等锁链表上
  •     LOS_DL_LIST          childrenList;                 /**< my children process list */ //孩子进程都挂到这里,形成双循环链表
  •     LOS_DL_LIST          exitChildList;                /**< my exit children process list */ //那些要退出孩子进程挂到这里,白发人送黑发人。
  •     LOS_DL_LIST          siblingList;                  /**< linkage in my parent's children list */ //兄弟进程链表, 56个民族是一家,来自同一个父进程.
  •     ProcessGroup         *group;                       /**< Process group to which a process belongs */ //所属进程组
  •     LOS_DL_LIST          subordinateGroupList;         /**< linkage in my group list */ //进程是组长时,有哪些组员进程
  •     UINT32               threadGroupID;                /**< Which thread group , is the main thread ID of the process */ //哪个线程组是进程的主线程ID
  •     UINT32               threadScheduleMap;            /**< The scheduling bitmap table for the thread group of the
  •                                                             process */ //进程的各线程调度位图
  •     LOS_DL_LIST          threadSiblingList;            /**< List of threads under this process *///进程的线程(任务)列表
  •     LOS_DL_LIST          threadPriQueueList[OS_PRIORITY_QUEUE_NUM]; /**< The process's thread group schedules the
  •                                                                          priority hash table */ //进程的线程组调度优先级哈希表
  •     volatile UINT32      threadNumber; /**< Number of threads alive under this process */ //此进程下的活动线程数
  •     UINT32               threadCount;  /**< Total number of threads created under this process */ //在此进程下创建的线程总数
  •     LOS_DL_LIST          waitList;     /**< The process holds the waitLits to support wait/waitpid *///进程持有等待链表以支持wait/waitpid
  • } LosProcessCB;

看个简单点的 pendList表示这个进程中所有被阻塞的任务(task)都会挂到这个链表上管理. 任务阻塞的原因很多,可能是申请互斥锁失败,可能等待事件读消息队列,还可能开了一个定时任务等等。

再来看一个复杂点的 threadPriQueueList,这又是干嘛的?从名字可以看出来是线程的队列链表,在鸿蒙内核线程就是任务(task),任务分等了32个优先级,同级的任务放在同一个双向链表中, 32级就是32个双向链表,所以是个链表数组,每条链表中存放的是已就绪等待被调度的任务。

双向链表是内核最重要的结构体,精读内核的路上它会反复的映入你的眼帘,理解它是理解内存运作的关键所在!

作者邮箱:weharmony@126.com

鸿蒙内核源码注释中文版 < Gitee仓 | CSDN仓 | Github仓 | Coding仓 >精读内核源码,中文注解分析,深挖地基工程,构建底层网图,四大码仓每日同步更新

鸿蒙源码分析系列篇 < CSDN | OSCHINA | WeHarmony | 公众号 >问答式导读,生活式比喻,表格化说明,图形化展示,主流站点每日同步更新


过年了,祝各位新年快乐

大奖18dj18vip-大奖18dj18娱乐官网

开通大奖18dj18vip论坛VIP会员,限时促销活动,全站任意发帖,发帖无限制,优先推荐您的品牌!(点我购买)

小黑屋|手机版|Archiver|地图|联系站长|腾讯云代金券|seo优化服务|大奖18dj18vip
广告服务/项目合作/会员购买:QQ 侵权举报邮箱: fuwu-sosoba@qq.com 举报流程必看 大奖18dj18vip建站时间:创建于2013年07月23日
免责声明:大奖18dj18vip所有的内容均来自互联网以及第三方作者自由发布,版权归原作者版权所有,大奖18dj18vip不承担任何的法律责任,若有侵权请来信告知,我们立即删除!
版权声明:大奖18dj18vip影视资源均收集自互联网,没有提供影片资源存储和下载,也未参与录制上传,若大奖18dj18vip收录的资源涉及您的版权或知识产权或其他利益,我们会立即删除

GMT+8, 2021-2-25 09:53 , Processed in 0.038105 second(s), 10 queries , Gzip On, MemCached On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表