趣谈Linux操作系统
刘超
网易杭州研究院云计算技术部首席架构师
立即订阅
19254 人已学习
课程目录
已完结 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操作系统
登录|注册

24 | 物理内存管理(下):会议室管理员如何分配会议室?

刘超 2019-05-22
前一节,前面我们解析了整页的分配机制。如果遇到小的对象,物理内存是如何分配的呢?这一节,我们一起来看一看。

小内存的分配

前面我们讲过,如果遇到小的对象,会使用 slub 分配器进行分配。那我们就先来解析它的工作原理。
还记得咱们创建进程的时候,会调用 dup_task_struct,它想要试图复制一个 task_struct 对象,需要先调用 alloc_task_struct_node,分配一个 task_struct 对象。
从这段代码可以看出,它调用了 kmem_cache_alloc_node 函数,在 task_struct 的缓存区域 task_struct_cachep 分配了一块内存。
static struct kmem_cache *task_struct_cachep;
task_struct_cachep = kmem_cache_create("task_struct",
arch_task_struct_size, align,
SLAB_PANIC|SLAB_NOTRACK|SLAB_ACCOUNT, NULL);
static inline struct task_struct *alloc_task_struct_node(int node)
{
return kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node);
}
static inline void free_task_struct(struct task_struct *tsk)
{
kmem_cache_free(task_struct_cachep, tsk);
}
在系统初始化的时候,task_struct_cachep 会被 kmem_cache_create 函数创建。这个函数也比较容易看懂,专门用于分配 task_struct 对象的缓存。这个缓存区的名字就叫 task_struct。缓存区中每一块的大小正好等于 task_struct 的大小,也即 arch_task_struct_size。
有了这个缓存区,每次创建 task_struct 的时候,我们不用到内存里面去分配,先在缓存里面看看有没有直接可用的,这就是 kmem_cache_alloc_node 的作用。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《趣谈Linux操作系统》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(23)

  • W.jyao
    真心看不懂了,😔😔😔

    作者回复: 多看几遍就好了

    2019-05-22
    1
    11
  • 欠债太多
    看到现在,代码越来越多,关于代码的阅读需要么?怎么去做呢

    作者回复: 重点关注流程,不关注细节

    2019-05-22
    9
  • 鲍勃
    果然和你的网络课程一样,越到后面越hold不住😂

    作者回复: 其实哪门课都一样哈

    2019-05-22
    8
  • 刘強
    这几节看起来吃力了,需要理解的外围知识很多!

    作者回复: 加油,多看几遍

    2019-05-22
    7
  • why
    - 小内存分配, 例如分配 task_struct 对象
        - 会调用 kmem_cache_alloc_node 函数, 从 task_struct 缓存区域 task_struct_cachep(在系统初始化时, 由 kmem_cache_create 创建) 分配一块内存
        - 使用 task_struct 完毕后, 调用 kmem_cache_free 回收到缓存池中
        - struct kmem_cache 用于表示缓存区信息, 缓存区即分配连续几个页的大块内存, 再切成小内存
        - 小内存即缓存区的每一项, 都由对象和指向下一项空闲小内存的指针组成(随机插入/删除+快速查找空闲)
        - struct kmem_cache 中三个 kmem_cache_order_objects 表示不同的需要分配的内存块大小的阶数和对象数
        - 分配缓存的小内存块由两个路径 fast path 和 slow path , 分别对应 struct kmem_cache 中的 kmem_cache_cpu 和 kmem_cache_node
        - 分配时先从 kmem_cache_cpu 分配, 若其无空闲, 再从 kmem_cache_node 分配, 还没有就从伙伴系统申请新内存块
        - struct kmem_cache_cpu 中
            - page 指向大内存块的第一个页
            - freelist 指向大内存块中第一个空闲项
            - partial 指向另一个大内存块的第一个页, 但该内存块有部分已分配出去, 当 page 满后, 在 partial 中找
        - struct kmem_cache_node
            - 也有 partial, 是一个链表, 存放部分空闲的多个大内存块, 若 kmem_cacche_cpu 中的 partial 也无空闲, 则在这找
        - 分配过程
            - kmem_cache_alloc_node->slab_alloc_node
            - 快速通道, 取出 kmem_cache_cpu 的 freelist , 若有空闲直接返回
            - 普通通道, 若 freelist 无空闲, 调用 `__slab_alloc`
            - `__slab_alloc` 会重新查看 freelist, 若还不满足, 查看 kmem_cache_cpu 的 partial
            - 若 partial 不为空, 用其替换 page, 并重新检查是否有空闲
            - 若还是无空闲, 调用 new_slab_objects
            - new_slab_objects 根据节点 id 找到对应 kmem_cache_node , 调用 get_partial_node
            - 首先从 kmem_cache_node 的 partial 链表拿下一大块内存, 替换 kmem_cache_cpu 的 page, 再取一块替换 kmem_cache_cpu 的 partial
            - 若 kmem_cache_node 也没有空闲, 则在 new_slab_objects 中调用 new_slab->allocate_slab->alloc_slab_page 根据某个 kmem_cache_order_objects 设置申请大块内存
    - 页面换出
        - 触发换出:
        - 1) 分配内存时发现没有空闲; 调用 `get_page_from_freelist->node_reclaim->__node_reclaim->shrink_node`
        - 2) 内存管理主动换出, 由内核线程 kswapd 实现
        - kswapd 在内存不紧张时休眠, 在内存紧张时检测内存 调用 balance_pgdat->kswapd_shrink_node->shrink_node
        - 页面都挂在 lru 链表中, 页面有两种类型: 匿名页; 文件内存映射页
        - 每一类有两个列表: active 和 inactive 列表
        - 要换出时, 从 inactive 列表中找到最不活跃的页换出
        - 更新列表, shrink_list 先缩减 active 列表, 再缩减不活跃列表
        - 缩减不活跃列表时对页面进行回收:
            - 匿名页回收: 分配 swap, 将内存也写入文件系统
            - 文件内存映射页: 将内存中的文件修改写入文件中
    2019-05-24
    6
  • 活的潇洒
    花了4个多小时终于把笔记做完
    分享给大家:
    https://www.cnblogs.com/luoahong/p/10907734.html

    作者回复: 赞

    2019-05-22
    6
  • 超超
    参考文章:https://mp.weixin.qq.com/s/6JVpke8bDKI9lvh_l6QF-w

    作者回复: 赞

    2019-07-17
    2
  • 超超
    1.系统在什么情况下才会使用SWAP?

    实际上,并不是等所有的物理内存都消耗完毕之后,才去使用swap的空间,什么时候使用是由swappiness 参数值控制。
    [root@rhce ~]# cat /proc/sys/vm/swappiness

    60
    该值默认值是60.

    swappiness=0的时候表示最大限度使用物理内存,然后才是 swap空间,

    swappiness=100的时候表示积极的使用swap分区,并且把内存上的数据及时的搬运到swap空间里面。

    现在服务器的内存动不动就是上百G,所以我们可以把这个参数值设置的低一些,让操作系统尽可能的使用物理内存,降低系统对swap的使用,从而提高系统的性能。

    2019-07-17
    2
  • 超超
    3. 如何查看swap分区
    swapon -s
    cat /proc/swaps
    free
    vmstat
    以上4类命令都可以查看swap分区的大小和使用情况

    作者回复: 赞

    2019-07-17
    1
  • 超超
    2. 如何修改swappiness参数?

    --临时性修改:

    [root@rhce ~]# sysctl vm.swappiness=10

    vm.swappiness = 10

    [root@rhce ~]# cat /proc/sys/vm/swappiness
    10
    这里我们的修改已经生效,但是如果我们重启了系统,又会变成60.

    --永久修改:
    在/etc/sysctl.conf 文件里添加如下参数:
    vm.swappiness=10
    或者:
    [root@rhce ~]# echo 'vm.swappiness=10' >>/etc/sysctl.conf

    保存,重启,就生效了。

    作者回复: 如此认真,典范啊

    2019-07-17
    1
  • guojiun
    https://events.static.linuxfound.org/sites/events/files/slides/slaballocators.pdf 這裡有清楚的視意圖,對照著看會更清楚!

    作者回复: 赞

    2019-05-22
    1
  • 俩孩儿他爸
    老师,slub存在回收机制吧?就是slub中空闲很多的时候,是不是会这些内存块释放,返回给系统呢?

    作者回复: 一个内存块的slub全部释放之后,整个页都会回收

    2019-08-29
  • 俩孩儿他爸
    老师,kmem_cache_cpu中的page和partial不是指向同一块内存区域的吧,为什么会这么设计呢?partial的作用是什么呢?

    作者回复: 不是同一块的。备用列表,当 page 满了,就会从这里找

    2019-08-29
  • 栋能
    我想知道文中 “对于缓存来讲,其实就是分配了连续几页的大内存块,然后根据缓存对象大小,切成小内存块” 中,小内存块和页大小是怎么个关系?按我的理解小内存块就是task_struct对象大小,一个页中有很多。而kmem_cache_cpu中对于中freelist是大内存块中的项,这个这个项和小内存块或task_struct有个什么关系?是大小一样呢,还是怎个关系?还有最后讲页面换出单位是内存节点,这个节点不可能是整个NUMA节吧,是指啥我没看明白

    作者回复: 这里的意思是每个NUMA节点,自己换出自己的,不是将整个NUMA节点都换出

    2019-07-23
  • 深几
    kswapd 在内存紧张的时候,开始工作,那么这个紧张的条件是什么?总的物理内存还是按照 zone 来区分呢?

    作者回复: 对每个NUMA结点来说,都有一个单独的kswapd守护进程

    2019-07-10
  • skye
    老师能讲讲大块内存的分配吗

    作者回复: mmap

    2019-06-21
  • Geek_54edc1
    查看分区情况:/proc/swaps
    2019-06-12
  • zhj
    麻烦问下,换出不活跃物理页的时候,对于原来进程A是无感知的,A中的页表保存了虚拟地址到物理地址的映射,在A视角看来还是原来大小的内存,但当A需要访问这个不活跃的页时,这个映射关系已经不成立,所以我的问题就是当换出发生的时候,对A的页表是进行了什么特殊处理,望老师答疑下

    作者回复: 在页表做了标记,说明已经换出了

    2019-05-30
  • 川云
    讲得真好,深入到代码层面,否则要是自己研究太困难了,不过也确实需要一定的Linux基础,根据老师的讲解再去看下linux内核的书籍,会提升的更快的

    作者回复: 谢谢,这门课主要强调流程,代码是个印证,不适合作为特别严肃的代码分析书籍看,为了突出内核工作机制和流程,删除和省略了很多内核代码

    2019-05-28
  • 周平
    老师,有个疑问,这些内存小块的分配及释放,都是在物理内存中完成的呢,还是在虚拟内存中完成再映射对对应的物理内存呢?

    作者回复: 物理内存分配完毕一整页的时候,会通过page_address分配一个虚拟地址,小块都是基于这个虚拟地址的。

    2019-05-27
收起评论
23
返回
顶部