内核中哪些地方会用到互斥锁?看图:

图中是内核有关模块对互斥锁初始化,有文件,有内存,用消息队列等等,使用面非常的广.其实在给内核源码加注的过程中,会看到大量的自旋锁和互斥锁,它们的存在有序的保证了内核和应用程序的正常运行.是非常基础和重要的功能.
概述
自旋锁 和 互斥锁 虽都是锁,但解决的问题不同, 自旋锁解决用于CPU核间共享内存的竞争,而互斥锁解决线程(任务)间共享内存的竞争.
自旋锁的特点是死守共享资源,拿不到锁,CPU选择睡眠,等待其他CPU释放资源.所以共享代码段不能太复杂,否则容易死锁,休克.
互斥锁的特点是拿不到锁往往原任务阻塞,切换到新任务运行.CPU是会一直跑的.这样很容易会想到几个问题:
第一:会出现很多任务在等同一把锁的情况出现,因为切换新任务也可能因要同一把锁而被阻塞,CPU又被调去跑新新任务了.这样就会出现一个等锁的链表.
第二:持有锁的一方再申请同一把锁时还能成功吗? 答案是可以的,这种锁叫递归锁,是鸿蒙内核默认方式.
第三:当优先级很高的A任务要锁失败,主动让出CPU进入睡眠,而如果持有锁的B任务优先级很低, 迟迟等不到调度不到B任务运行,无法释放锁怎么办?
答案是会临时调整B任务的优先级,调到A一样高,这样B能很快的被调度到,等B释放锁后其优先级又会被还原.所以一个任务的优先级会看情况时高时低.
第四:B任务释放锁之后要主动唤醒等锁的任务链表,使他们能加入就绪队列,等待被调度.调度算法是一视同仁的,它只看优先级.
带着这些问题,进入鸿蒙内核互斥锁的实现代码,本篇代码量较大, 每行代码都一一注解说明.
互斥锁长什么样?
初始化
留意mutex->muxList,这又是一个双向链表, 双向链表是内核最重要的结构体,不仅仅是鸿蒙内核,在linux内核中(list_head)又何尝不是,牢牢的寄生在宿主结构体上.muxList上挂的是未来所有等待这把锁的任务.
三种申请模式
申请互斥锁有三种模式:无阻塞模式、永久阻塞模式、定时阻塞模式。
无阻塞模式:即任务申请互斥锁时,入参timeout等于0。若当前没有任务持有该互斥锁,或者持有该互斥锁的任务和申请该互斥锁的任务为同一个任务,则申请成功,否则立即返回申请失败。
永久阻塞模式:即任务申请互斥锁时,入参timeout等于0xFFFFFFFF。若当前没有任务持有该互斥锁,则申请成功。否则,任务进入阻塞态,系统切换到就绪任务中优先级最高者继续执行。任务进入阻塞态后,直到有其他任务释放该互斥锁,阻塞任务才会重新得以执行。
定时阻塞模式:即任务申请互斥锁时,0<timeout<0xFFFFFFFF。若当前没有任务持有该互斥锁,则申请成功。否则该任务进入阻塞态,系统切换到就绪任务中优先级最高者继续执行。任务进入阻塞态后,超时前如果有其他任务释放该互斥锁,则该任务可成功获取互斥锁继续执行,若超时前未获取到该互斥锁,接口将返回超时错误码。
如果有任务阻塞于该互斥锁,则唤醒被阻塞任务中优先级最高的,该任务进入就绪态,并进行任务调度。
如果没有任务阻塞于该互斥锁,则互斥锁释放成功。
申请互斥锁主函数 OsMuxPendOp
释放锁的主体函数 OsMuxPostOp
编程实例
本实例实现如下流程。
- 任务Example_TaskEntry创建一个互斥锁,锁任务调度,创建两个任务Example_MutexTask1、Example_MutexTask2。Example_MutexTask2优先级高于Example_MutexTask1,解锁任务调度,然后Example_TaskEntry任务休眠300Tick。
- Example_MutexTask2被调度,以永久阻塞模式申请互斥锁,并成功获取到该互斥锁,然后任务休眠100Tick,Example_MutexTask2挂起,Example_MutexTask1被唤醒。
- Example_MutexTask1以定时阻塞模式申请互斥锁,等待时间为10Tick,因互斥锁仍被Example_MutexTask2持有,Example_MutexTask1挂起。10Tick超时时间到达后,Example_MutexTask1被唤醒,以永久阻塞模式申请互斥锁,因互斥锁仍被Example_MutexTask2持有,Example_MutexTask1挂起。
- 100Tick休眠时间到达后,Example_MutexTask2被唤醒, 释放互斥锁,唤醒Example_MutexTask1。Example_MutexTask1成功获取到互斥锁后,释放锁。
- 300Tick休眠时间到达后,任务Example_TaskEntry被调度运行,删除互斥锁,删除两个任务。
结果验证
总结
1.互斥锁解决的是任务间竞争共享内存的问题.
2.申请锁失败的任务会进入睡眠OsTaskWait,内核会比较持有锁的任务和申请锁任务的优先级,把持有锁的任务优先级调到尽可能的高,以便更快的被调度执行,早日释放锁.
3.释放锁的任务会在等锁链表中找一个高优先级任务,通过OsTaskWake唤醒它,并向调度算法申请调度.但要注意,调度算法只是按优先级来调度,并不保证调度后的任务一定是要唤醒的任务.
4.互斥锁篇关键是看懂 OsMuxPendOp 和 OsMuxPostOp 两个函数.
经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?
为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)
如何快速入门?
1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

基于ArkTS 开发
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

鸿蒙开发面试真题(含参考答案)

OpenHarmony 开发环境搭建

《OpenHarmony源码解析》
- 搭建开发环境
- Windows 开发环境的搭建
- Ubuntu 开发环境搭建
- Linux 与 Windows 之间的文件共享
- ……
- 系统架构分析
- 构建子系统
- 启动流程
- 子系统
- 分布式任务调度子系统
- 分布式通信子系统
- 驱动子系统
- ……

OpenHarmony 设备开发学习手册

写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。

所有评论(0)