本篇关键词:进程上下文、、、
下载 >> 离线文档.鸿蒙内核源码分析(百篇博客分析.挖透鸿蒙内核).pdf
内核汇编相关篇为:
- v74.01 鸿蒙内核源码分析(编码方式) | 机器指令是如何编码的
- v75.03 鸿蒙内核源码分析(汇编基础) | CPU上班也要打卡
- v76.04 鸿蒙内核源码分析(汇编传参) | 如何传递复杂的参数
- v77.01 鸿蒙内核源码分析(链接脚本) | 正在制作中 ...
- v78.01 鸿蒙内核源码分析(内核启动) | 从汇编到main()
- v79.01 鸿蒙内核源码分析(进程切换) | 正在制作中 ...
- v80.03 鸿蒙内核源码分析(任务切换) | 看汇编如何切换任务
- v81.05 鸿蒙内核源码分析(中断切换) | 系统因中断活力四射
- v82.06 鸿蒙内核源码分析(异常接管) | 社会很单纯 复杂的是人
- v83.01 鸿蒙内核源码分析(缺页中断) | 正在制作中 ...
站长正在努力制作中 ... , 请客官稍等时日 , 可前往其他篇幅观看
再看下那些地方会调用 LOS_ArchMmuContextSwitch
,下图一目了然。
哪些地方会切换mmu
上下文
第一:通过调度算法,被选中的进程的空间改变了,自然映射页表就跟着变了,需要切换mmu上下文,还是直接看代码。代码不是很多,就都贴出来了,都加了注释,不记得调度算法的可去系列篇中看 鸿蒙内核源码分析(调度机制篇),里面有详细的阐述。
//调度算法-进程切换 STATIC VOID OsSchedSwitchProcess(LosProcessCB *runProcess, LosProcessCB *newProcess) { if (runProcess == newProcess) { return; } #if (LOSCFG_KERNEL_SMP == YES) runProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_DEC(runProcess->processStatus); newProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_ADD(newProcess->processStatus); LOS_ASSERT(!(OS_PROCESS_GET_RUNTASK_COUNT(newProcess->processStatus) > LOSCFG_KERNEL_CORE_NUM)); if (OS_PROCESS_GET_RUNTASK_COUNT(runProcess->processStatus) == 0) {//获取当前进程的任务数量 #endif runProcess->processStatus &= ~OS_PROCESS_STATUS_RUNNING; if ((runProcess->threadNumber > 1) && !(runProcess->processStatus & OS_PROCESS_STATUS_READY)) { runProcess->processStatus |= OS_PROCESS_STATUS_PEND; } #if (LOSCFG_KERNEL_SMP == YES) } #endif LOS_ASSERT(!(newProcess->processStatus & OS_PROCESS_STATUS_PEND));//断言进程不是阻塞状态 newProcess->processStatus |= OS_PROCESS_STATUS_RUNNING;//设置进程状态为运行状态 if (OsProcessIsUserMode(newProcess)) {//用户模式下切换进程mmu上下文 LOS_ArchMmuContextSwitch(&newProcess->vmSpace->archMmu);//新进程->虚拟空间中的->Mmu部分入参 } #ifdef LOSCFG_KERNEL_CPUP OsProcessCycleEndStart(newProcess->processID, OS_PROCESS_GET_RUNTASK_COUNT(runProcess->processStatus) + 1); #endif /* LOSCFG_KERNEL_CPUP */ OsCurrProcessSet(newProcess);//将进程置为 g_runProcess if ((newProcess->timeSlice == 0) && (newProcess->policy == LOS_SCHED_RR)) {//为用完时间片或初始进程分配时间片 newProcess->timeSlice = OS_PROCESS_SCHED_RR_INTERVAL;//重新分配时间片,默认 20ms } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33这里再啰嗦一句,系列篇中已经说了两个上下文切换了,一个是这里的因进程切换引起的mmu上下文切换,还一个是因task切换引起的CPU的上下文切换,还能想起来吗?
第二:是加载
ELF
文件的时候会切换mmu
,一个崭新的进程诞生了,具体翻看(进程映像篇)。其余是虚拟空间回收和刷新空间的时候,这个就自己看代码去吧。mmu是如何快速的通过虚拟地址找到物理地址的呢?答案是:TLB
,注意上面还有个TTB
,一个是寄存器, 一个是cache
,别搞混了。
asid寄存器
asid(Adress Space ID) 进程标识符,属于CP15协处理器的C13号寄存器,ASID可用来唯一标识进程,并为进程提供地址空间保护。当TLB试图解析虚拟页号时,它确保当前运行进程的ASID与虚拟页相关的ASID相匹配。如果不匹配,那么就作为TLB失效。除了提供地址空间保护外,ASID允许TLB同时包含多个进程的条目。如果TLB不支持独立的ASID,每次选择一个页表时(例如,上下文切换时),TLB就必须被冲刷(flushed)或删除,以确保下一个进程不会使用错误的地址转换。
TLB页表中有一个bit来指明当前的entry是global(nG=0,所有process都可以访问)还是non-global(nG=1,only本process允许访问)。如果是global类型,则TLB中不会tag ASID;如果是non-global类型,则TLB会tag上ASID,且MMU在TLB中查询时需要判断这个ASID和当前进程的ASID是否一致,只有一致才证明这条entry当前process有权限访问。
看到了吗?如果每次mmu上下文切换时,把TLB全部刷新已保证TLB中全是新进程的映射表,固然是可以,但效率太低了!!!进程的切换其实是秒级亚秒级的,地址的虚实转换是何等的频繁啊,怎么会这么现实呢,真实的情况是TLB中有很多很多其他进程占用的物理内存的记录还在,当然他们对物理内存的使用权也还在。所以当应用程序 new了10M内存以为是属于自己的时候,其实在内核层面根本就不属于你,还是别人在用,只有你用了1M的那一瞬间真正1M物理内存才属于你,而且当你的进程被其他进程切换后,很大可能你用的那1M也已经不在物理内存中了,已经被置换到硬盘上了。明白了吗?只关注应用开发的同学当然可以说这关我鸟事,给我的感觉有就行了,但想熟悉内核的同学就必须要明白,这是每分每秒都在发生的事情。
最后一个函数留给大家,asid是如何分配的?
/* allocate and free asid */
status_t OsAllocAsid(UINT32 *asid)
{
UINT32 flags;
LOS_SpinLockSave(&g_cpuAsidLock, &flags);
UINT32 firstZeroBit = LOS_BitmapFfz(g_asidPool, 1UL << MMU_ARM_ASID_BITS);
if (firstZeroBit >= 0 && firstZeroBit < (1UL << MMU_ARM_ASID_BITS)) {
LOS_BitmapSetNBits(g_asidPool, firstZeroBit, 1);
*asid = firstZeroBit;
LOS_SpinUnlockRestore(&g_cpuAsidLock, flags);
return LOS_OK;
}
LOS_SpinUnlockRestore(&g_cpuAsidLock, flags);
return firstZeroBit;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
百文说内核 | 抓住主脉络
- 百文相当于摸出内核的肌肉和器官系统,让人开始丰满有立体感,因是直接从注释源码起步,在加注释过程中,每每有心得处就整理,慢慢形成了以下文章。内容立足源码,常以生活场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解记忆。说别人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思。更希望让内核变得栩栩如生,倍感亲切。
- 与代码需不断
debug
一样,文章内容会存在不少错漏之处,请多包涵,但会反复修正,持续更新,v**.xx
代表文章序号和修改的次数,精雕细琢,言简意赅,力求打造精品内容。 - 百文在 < 鸿蒙研究站 | 开源中国 | 博客园 | 51cto | csdn | 知乎 | 掘金 > 站点发布,百篇博客系列目录如下。
按功能模块:
百万注源码 | 处处扣细节
百万汉字注解内核目的是要看清楚其毛细血管,细胞结构,等于在拿放大镜看内核。内核并不神秘,带着问题去源码中找答案是很容易上瘾的,你会发现很多文章对一些问题的解读是错误的,或者说不深刻难以自圆其说,你会慢慢形成自己新的解读,而新的解读又会碰到新的问题,如此层层递进,滚滚向前,拿着放大镜根本不愿意放手。
关注不迷路 | 代码即人生
- 互联网从业十五年,计算机硕士,技术副总裁
- 关注我,持续更新四十年,即聊技术也聊人生
- 交有趣靠谱的人;做难而正确的事
- 不做作,不炒作,只唯真
- 不唯上,不唯书,只唯实
据说喜欢 点赞 + 分享 的,后来都成了大神。😃