趣谈Linux操作系统
刘超
网易杭州研究院云计算技术部首席架构师
立即订阅
19398 人已学习
课程目录
已完结 72 讲
0/4登录后,你可以任选4讲全文学习。
入门准备篇 (3讲)
开篇词 | 为什么要学习Linux操作系统?
免费
01 | 入学测验:你究竟对Linux操作系统了解多少?
02 | 学习路径:爬过这六个陡坡,你就能对Linux了如指掌
核心原理篇:第一部分 Linux操作系统综述 (3讲)
03 | 你可以把Linux内核当成一家软件外包公司的老板
04 | 快速上手几个Linux命令:每家公司都有自己的黑话
05 | 学会几个系统调用:咱们公司能接哪些类型的项目?
核心原理篇:第二部分 系统初始化 (4讲)
06 | x86架构:有了开放的架构,才能打造开放的营商环境
07 | 从BIOS到bootloader:创业伊始,有活儿老板自己上
08 | 内核初始化:生意做大了就得成立公司
09 | 系统调用:公司成立好了就要开始接项目
核心原理篇:第三部分 进程管理 (10讲)
10 | 进程:公司接这么多项目,如何管?
11 | 线程:如何让复杂的项目并行执行?
12 | 进程数据结构(上):项目多了就需要项目管理系统
13 | 进程数据结构(中):项目多了就需要项目管理系统
14 | 进程数据结构(下):项目多了就需要项目管理系统
15 | 调度(上):如何制定项目管理流程?
16 | 调度(中):主动调度是如何发生的?
17 | 调度(下):抢占式调度是如何发生的?
18 | 进程的创建:如何发起一个新项目?
19 | 线程的创建:如何执行一个新子项目?
核心原理篇:第四部分 内存管理 (7讲)
20 | 内存管理(上):为客户保密,规划进程内存空间布局
21 | 内存管理(下):为客户保密,项目组独享会议室封闭开发
22 | 进程空间管理:项目组还可以自行布置会议室
23 | 物理内存管理(上):会议室管理员如何分配会议室?
24 | 物理内存管理(下):会议室管理员如何分配会议室?
25 | 用户态内存映射:如何找到正确的会议室?
26 | 内核态内存映射:如何找到正确的会议室?
核心原理篇:第五部分 文件系统 (4讲)
27 | 文件系统:项目成果要归档,我们就需要档案库
28 | 硬盘文件系统:如何最合理地组织档案库的文档?
29 | 虚拟文件系统:文件多了就需要档案管理系统
30 | 文件缓存:常用文档应该放在触手可得的地方
核心原理篇:第六部分 输入输出系统 (5讲)
31 | 输入与输出:如何建立售前售后生态体系?
32 | 字符设备(上):如何建立直销模式?
33 | 字符设备(下):如何建立直销模式?
34 | 块设备(上):如何建立代理商销售模式?
35 | 块设备(下):如何建立代理商销售模式?
核心原理篇:第七部分 进程间通信 (7讲)
36 | 进程间通信:遇到大项目需要项目组之间的合作才行
37 | 信号(上):项目组A完成了,如何及时通知项目组B?
38 | 信号(下):项目组A完成了,如何及时通知项目组B?
39 | 管道:项目组A完成了,如何交接给项目组B?
40 | IPC(上):不同项目组之间抢资源,如何协调?
41 | IPC(中):不同项目组之间抢资源,如何协调?
42 | IPC(下):不同项目组之间抢资源,如何协调?
核心原理篇:第八部分 网络系统 (7讲)
43 预习 | Socket通信之网络协议基本原理
43 | Socket通信:遇上特大项目,要学会和其他公司合作
44 | Socket内核数据结构:如何成立特大项目合作部?
45 | 发送网络包(上):如何表达我们想让合作伙伴做什么?
46 | 发送网络包(下):如何表达我们想让合作伙伴做什么?
47 | 接收网络包(上):如何搞明白合作伙伴让我们做什么?
48 | 接收网络包(下):如何搞明白合作伙伴让我们做什么?
核心原理篇:第九部分 虚拟化 (7讲)
49 | 虚拟机:如何成立子公司,让公司变集团?
50 | 计算虚拟化之CPU(上):如何复用集团的人力资源?
51 | 计算虚拟化之CPU(下):如何复用集团的人力资源?
52 | 计算虚拟化之内存:如何建立独立的办公室?
53 | 存储虚拟化(上):如何建立自己保管的单独档案库?
54 | 存储虚拟化(下):如何建立自己保管的单独档案库?
55 | 网络虚拟化:如何成立独立的合作部?
核心原理篇:第十部分 容器化 (4讲)
56 | 容器:大公司为保持创新,鼓励内部创业
57 | Namespace技术:内部创业公司应该独立运营
58 | CGroup技术:内部创业公司应该独立核算成本
59 | 数据中心操作系统:上市敲钟
实战串讲篇 (9讲)
60 | 搭建操作系统实验环境(上):授人以鱼不如授人以渔
61 | 搭建操作系统实验环境(下):授人以鱼不如授人以渔
62 | 知识串讲:用一个创业故事串起操作系统原理(一)
63 | 知识串讲:用一个创业故事串起操作系统原理(二)
64 | 知识串讲:用一个创业故事串起操作系统原理(三)
65 | 知识串讲:用一个创业故事串起操作系统原理(四)
66 | 知识串讲:用一个创业故事串起操作系统原理(五)
67 | 期末测试:这些操作系统问题,你真的掌握了吗?
结束语 | 永远别轻视任何技术,也永远别轻视自己
免费
专栏加餐 (2讲)
学习攻略(一):学好操作系统,需要掌握哪些前置知识?
“趣谈Linux操作系统”食用指南
免费
趣谈Linux操作系统
登录|注册

26 | 内核态内存映射:如何找到正确的会议室?

刘超 2019-05-27
前面讲用户态内存映射机制的时候,我们已经多次引申出了内核的映射机制,但是咱们都暂时放了放,这一节我们就来详细解析一下,让你彻底搞懂它。
首先,你要知道,内核态的内存映射机制,主要包含以下几个部分:
内核态内存映射函数 vmalloc、kmap_atomic 是如何工作的;
内核态页表是放在哪里的,如何工作的?swapper_pg_dir 是怎么回事;
出现了内核态缺页异常应该怎么办?

内核页表

和用户态页表不同,在系统初始化的时候,我们就要创建内核页表了。
我们从内核页表的根 swapper_pg_dir 开始找线索,在 arch/x86/include/asm/pgtable_64.h 中就能找到它的定义。
extern pud_t level3_kernel_pgt[512];
extern pud_t level3_ident_pgt[512];
extern pmd_t level2_kernel_pgt[512];
extern pmd_t level2_fixmap_pgt[512];
extern pmd_t level2_ident_pgt[512];
extern pte_t level1_fixmap_pgt[512];
extern pgd_t init_top_pgt[];
#define swapper_pg_dir init_top_pgt
swapper_pg_dir 指向内核最顶级的目录 pgd,同时出现的还有几个页表目录。我们可以回忆一下,64 位系统的虚拟地址空间的布局,其中 XXX_ident_pgt 对应的是直接映射区,XXX_kernel_pgt 对应的是内核代码区,XXX_fixmap_pgt 对应的是固定映射区。
它们是在哪里初始化的呢?在汇编语言的文件里面的 arch\x86\kernel\head_64.S。这段代码比较难看懂,你只要明白它是干什么的就行了。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《趣谈Linux操作系统》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(13)

  • 活的潇洒
    决心从头把计算机所有的基础课程全部补上,夯实基础,一定要坚持到最后
    day26笔记:https://www.cnblogs.com/luoahong/p/10931320.html
    2019-05-29
    7
  • 没心没肺
    好恐怖,看到这里,是硬看了

    作者回复: 不怕不怕

    2019-07-05
    6
  • Sentry
    内核能用c语言编写,是不是意味着用c可以直接操作物理内存,另外linux上的c语言编译器是用什么语言开发的,c语言实现了自举吗,c语言跨平台底层原理是什么,请老师答疑解惑。

    作者回复: 是因为C语言编译完了就直接是硬件能够识别的二进制,不像java,需要jvm才能运行。C语言不用自举,除了第一个开发C语言的,需要用汇编来做,后面都可以用锤子造锤子

    2019-05-27
    5
  • why
    - 涉及三块内容:
        - 内存映射函数 vmalloc, kmap_atomic
        - 内核态页表存放位置和工作流程
        - 内核态缺页异常处理
    - 内核态页表, 系统初始化时就创建
        - swapper_pg_dir 指向内核顶级页目录 pgd
            - xxx_ident/kernel/fixmap_pgt 分别是直接映射/内核代码/固定映射的 xxx 级页表目录
        - 创建内核态页表
            - swapper_pg_dir 指向 init_top_pgt, 是 ELF 文件的全局变量, 因此再内存管理初始化之间就存在
            - init_top_pgt 先初始化了三项
                - 第一项指向 level3_ident_pgt (内核代码段的某个虚拟地址) 减去 __START_KERNEL_MAP (内核代码起始虚拟地址) 得到实际物理地址
                - 第二项也是指向 level3_ident_pgt
                - 第三项指向 level3_kernel_pgt 内核代码区
        - 初始化各页表项, 指向下一集目录
            - 页表覆盖范围较小, 内核代码 512MB, 直接映射区 1GB
            - 内核态也定义 mm_struct 指向 swapper_pg_dir
            - 初始化内核态页表, start_kernel→ setup_arch
                - load_cr3(swapper_pg_dir) 并刷新 TLB
                - 调用 init_mem_mapping→kernel_physical_mapping_init, 用 __va 将物理地址映射到虚拟地址, 再创建映射页表项
                - CPU 在保护模式下访问虚拟地址都必须通过 cr3, 系统只能照做
                - 在 load_cr3 之前, 通过 early_top_pgt 完成映射
    - vmalloc 和 kmap_atomic
        - 内核的虚拟地址空间 vmalloc 区域用于映射
        - kmap_atomic 临时映射
            - 32 位, 调用 set_pte 通过内核页表临时映射
            - 64 位, 调用 page_address→lowmem_page_address 进行映射
    - 内核态缺页异常
        - kmap_atomic 直接创建页表进行映射
        - vmalloc 只分配内核虚拟地址, 访问时触发缺页中断, 调用 do_page_fault→vmalloc_fault 用于关联内核页表项
    - kmem_cache 和 kmalloc 用于保存内核数据结构, 不会被换出; 而内核 vmalloc 会被换出
    2019-05-27
    2
  • 活的潇洒
    坚持完整的学到底,坚持完整的笔记到底
    day26 学习笔记:https://www.cnblogs.com/luoahong/p/10931320.html

    作者回复: 加油

    2019-05-27
    2
  • Bing
    用malloc申请的内存,进程退出时,操作系统是否会释放

    作者回复: 当然会啊,虚拟内存嘛

    2019-08-15
    1
  • 莫名
    👍看起来很有感觉,先讲用户态、内核态虚拟内存的管理,然后讲物理内存的管理,最后讲用户态、内核态虚拟内存与物理内存如何建立关联。

    作者回复: 赞,有感觉就好,要的就是心动

    2019-07-18
    1
  • LDxy
    操作系统是如何知道计算机上有多少物理内存的呢?

    作者回复: 初始化的时候,会检测硬件

    2019-06-02
    1
  • 陈志恒
    对于内存,要提醒自己内核态和用户态的概念,虚拟地址和物理地址的概念!
    2019-11-25
  • 陈志恒
    整个内存的讲解(这个专栏内容如果一下看不懂直接跳总结部分,甚至每章的最后,现有个整体认识,再返回去看细节,会容易很多)
    2019-11-25
  • kdb_reboot
    老师,针对内存管理有什么资料推荐吗,看的有点晕。发现了一件事情:虽然老师讲的很好,但是如果针对个人,看专栏的话,还是有很多隐含信息需要自己去了解
    2019-10-02
  • 俩孩儿他爸
    page_address的实现如下:

    ```
    /**
     * page_address - get the mapped virtual address of a page
     * @page: &struct page to get the virtual address of
     *
     * Returns the page's virtual address.
     */
    void *page_address(const struct page *page)
    {
    unsigned long flags;
    void *ret;
    struct page_address_slot *pas;

    if (!PageHighMem(page))
    return lowmem_page_address(page);

    pas = page_slot(page);
    ret = NULL;
    spin_lock_irqsave(&pas->lock, flags);
    if (!list_empty(&pas->lh)) {
    struct page_address_map *pam;

    list_for_each_entry(pam, &pas->lh, list) {
    if (pam->page == page) {
    ret = pam->virtual;
    goto done;
    }
    }
    }
    done:
    spin_unlock_irqrestore(&pas->lock, flags);
    return ret;
    }
    ```

    - 如果不是高端内存,物理地址和虚拟地址之间的转换相对比较简单,直接使用lowmme_page_address进行转换,前面提到过这个函数;
    - 对于非高端内存页,通过page_slot计算出pas,pas保存在由pagez作为key的hash表page_address_htable中;
    - 遍历pas->lh双向链表,链表的节点保存有page的地址和page所对应的虚拟地址,通过page,可以确定page对应的虚拟地址。
    2019-09-03
  • 栋能
    没太看懂kmalloc又是从哪里来的,是写错了么?(这个我还特意往前找了下,以为是kmmap,用于内存映射区的呢)

    作者回复: kmalloc内核空间内存申请函数。

    2019-07-25
收起评论
13
返回
顶部