本篇关键词:进程上下文、、、

下载 >> 离线文档.鸿蒙内核源码分析(百篇博客分析.挖透鸿蒙内核).pdf

内核汇编相关篇为:

站长正在努力制作中 ... , 请客官稍等时日 , 可前往其他篇幅观看

再看下那些地方会调用 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;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

百文说内核 | 抓住主脉络

  • 百文相当于摸出内核的肌肉和器官系统,让人开始丰满有立体感,因是直接从注释源码起步,在加注释过程中,每每有心得处就整理,慢慢形成了以下文章。内容立足源码,常以生活场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解记忆。说别人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思。更希望让内核变得栩栩如生,倍感亲切。
  • 与代码需不断debug一样,文章内容会存在不少错漏之处,请多包涵,但会反复修正,持续更新,v**.xx 代表文章序号和修改的次数,精雕细琢,言简意赅,力求打造精品内容。
  • 百文在 < 鸿蒙研究站 | 开源中国 | 博客园 | 51cto | csdn | 知乎 | 掘金 > 站点发布,鸿蒙研究站 | weharmonyos 中回复 百文 可方便阅读。

按功能模块:

百万注源码 | 处处扣细节

  • 百万汉字注解内核目的是要看清楚其毛细血管,细胞结构,等于在拿放大镜看内核。内核并不神秘,带着问题去源码中找答案是很容易上瘾的,你会发现很多文章对一些问题的解读是错误的,或者说不深刻难以自圆其说,你会慢慢形成自己新的解读,而新的解读又会碰到新的问题,如此层层递进,滚滚向前,拿着放大镜根本不愿意放手。

  • < gitee | github | coding | gitcode > 四大码仓推送 | 同步官方源码,鸿蒙研究站 | weharmonyos 中回复 百万 可方便阅读。

关注不迷路 | 代码即人生

据说喜欢点赞分享的,后来都成了大神。😃