From cc3e9344c57d8683d038f4104514c7544b5e8f67 Mon Sep 17 00:00:00 2001 From: gatieme Date: Wed, 31 Aug 2016 12:34:03 +0800 Subject: [PATCH] ... --- .../02-memory/05-slaballocator/README.md | 72 ++++++++++++++++--- study/kernel/02-memory/06-highmem/README.md | 46 ------------ .../kernel/02-memory/07-pagereclaim/README.md | 46 ------------ .../02-memory/08-pageswapping/README.md | 46 ------------ study/kernel/03-vmarea/README.md | 28 ++++++++ 5 files changed, 91 insertions(+), 147 deletions(-) delete mode 100644 study/kernel/02-memory/06-highmem/README.md delete mode 100644 study/kernel/02-memory/07-pagereclaim/README.md delete mode 100644 study/kernel/02-memory/08-pageswapping/README.md create mode 100644 study/kernel/03-vmarea/README.md diff --git a/study/kernel/02-memory/05-slaballocator/README.md b/study/kernel/02-memory/05-slaballocator/README.md index 56b2ab7..d56e75a 100644 --- a/study/kernel/02-memory/05-slaballocator/README.md +++ b/study/kernel/02-memory/05-slaballocator/README.md @@ -719,18 +719,55 @@ kmem_cache_init可以分为六个阶段 ```cpp mm/slab.c -struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) +struct kmem_cache *kmem_cache_create(const char *name, + size_t size, + size_t align, + unsigned long flags, + void (*ctor)(void *)) ``` 除了可读的`name`随后会出现在`/proc/slabinfo`以外, 该函数需要被管理对象以字节计的长度, 在对齐数据时使用的偏移量(`align`, 几乎所有的情形下都是0),flags中是一组标志,而ctor是构造函数. + + 该函数定义在[mm/slab_common.c?v=4.7, line 388](http://lxr.free-electrons.com/source/mm/slab_common.c?v=4.7#L388) -##4.4 分配对象 +| 参数 | 描述 | +|:-----:|:-----:| +| name | 存放着告诉缓存的名字 | +| size | 告诉缓存中每个元素的大小 | +| align | slab内第一个对象的偏移, 用来确保在页内进行特定的对齐, 通常情况下为0, 即标准对齐 | +| flags |配置项, 用来控制告诉缓存的行为. | +| ctor | 高速缓存的构造函数. 只有在新的页追加到高速缓存时, 构造函数才被调用 | + +flags参数是可选的配置项, 用来控制高速缓存的行为. 它可以为0, 表示没有特殊的行为, 或者与以下标志中的一个或多个"或"运算. + +| flags标志 | 描述 | +|:----------:|:-----:| +| SLAB_HWCACHE_ALIGN | | +| SLAB_POISON | | +| SLAB_RED_ZONE | | +| SLAB_PANIC | | +| SLAB_CACHE_DMA | | + + +关于最后一个参数ctor是告诉缓存的构造函数. 只有在新的页追加到高速缓存时, 构造函数才被调用. 实际上, Linux内核的高速缓存不使用构造函数. 事实上这里曾经还有过一个析构函数参数, 但是由于内核代码不使用它, 因此已经被抛弃了. 你可以将ctor参数赋值为NULL. + +`kmem_cache_create`在成功时返回一个指向所构造的高速缓存的针; 否则, 返回NULL. 注意该函数可能会睡眠, 因此不能再中断上下文中调用. + + + +##4.4 分配对象kmem_cache_alloc ------- -`kmem_cache_alloc`用于从特定的缓存获取对象. 类似于所有的`malloc`函数, 其结果可能是指向分配内存区的指针, 也可能分配失败, 返回`NULL`指针. +`kmem_cache_alloc`用于从特定的缓存获取对象. 类似于所有的`malloc`函数, 其结果可能是指向分配内存区的指针, 也可能分配失败, 返回`NULL`指针. + + +>void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) + + +该函数从给定的高速缓存cachep中返回一个指向对象的指针. 如果高速缓存中的所有slab中没有空闲的对象, 那么slab层就必须通过kmem_getpages获取新的页, flags的值传递给__get_free_pages函数. 这与我们之前所看到的标志相同. 你用到的应该是GFP_KERNEL或GFP_ATOMIC。 该函数需要两个参数 : 用于获取对象的缓存, 以及精确描述分配特征的标志变量. 之前提到的任何GFP_值都可以用于指定标志 @@ -757,17 +794,18 @@ EXPORT_SYMBOL(kmem_cache_alloc); ``` -##4.5 缓存的增长 -------- 给出了cache_grow的代码流程图 -##4.6 释放对象 +##4.5 释放对象kmem_cache_free ------- -如果一个分配的对象已经不再需要, 那么必须使用`kmem_cache_free`返回给`slab`分配器. +如果一个分配的对象已经不再需要, 那么必须使用`kmem_cache_free`将对象释放, 并返回给`slab`分配器. 这样就能把cachep中的对象标记为空闲. + +>void kmem_cache_free(struct kmem_cache *cachep, void *objp) + 每一个分配器都应该实现一个`kmem_cache_free`函数 @@ -788,7 +826,7 @@ EXPORT_SYMBOL(kmem_cache_alloc); ```cpp -792 /** +/** * kmem_cache_free - Deallocate an object * @cachep: The cache the allocation was from. * @objp: The previously allocated object. @@ -815,7 +853,7 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) EXPORT_SYMBOL(kmem_cache_free); ``` -##4.7 销毁缓存 +##4.6 销毁缓存 ------- @@ -832,6 +870,15 @@ EXPORT_SYMBOL(kmem_cache_free); * 从`cache_cache`链表移除相关数据。 +与kmem_cache_create类似, 不能在中断上下文中调用这个函数. 因为它也可能睡眠. 调用该函数之前必须确保一下两个条件 + +* 告诉缓存中所有slab都必须是NULL, 其实, 不管哪个slab中, 只要还有一个对象被分配出去并正在使用, 那么就不能撤销该告诉缓存 + +* 在调用`kmem_cache_destroy`过程中, 不再访问这个高速缓存. 调用者必须确保这种同步. + +该函数在成功时返回0, 否则返回非0. + + slab分配器中该函数定义在[mm/slab_common.c?v=4.7, line 706](http://lxr.free-electrons.com/source/mm/slab_common.c?v=4.7#L706) ```cpp @@ -874,6 +921,13 @@ out_unlock: EXPORT_SYMBOL(kmem_cache_destroy); ``` +##4.7 +------- + +我们来讲解一个slab分配器使用的鲜活的例子. 这个例子创建了task_struct结构, 取自kernel/fork.c + + + ##5 通用缓存 ------- diff --git a/study/kernel/02-memory/06-highmem/README.md b/study/kernel/02-memory/06-highmem/README.md deleted file mode 100644 index 1a3d0ec..0000000 --- a/study/kernel/02-memory/06-highmem/README.md +++ /dev/null @@ -1,46 +0,0 @@ -服务器体系与共享存储器架构 -======= - -| 日期 | 内核版本 | 架构| 作者 | GitHub| CSDN | -| ------- |:-------:|:-------:|:-------:|:-------:|:-------:| -| 2016-06-14 | [Linux-4.7](http://lxr.free-electrons.com/source/?v=4.7) | X86 & arm | [gatieme](http://blog.csdn.net/gatieme) | [LinuxDeviceDrivers](https://github.com/gatieme/LDD-LinuxDeviceDrivers) | [Linux内存管理](http://blog.csdn.net/gatieme/article/category/6225543) | - - -#1 目录 -------- - -| CSDN | GitHub | -|:-------:|:-------:| -| 描述物理内存 | -| 页表管理 | -| 初始化内存挂历 | -| 物理内存的管理 | -| slab分配器 | - -| 非连续内存分配 | -| 高端内存管理 | -| 页面帧回收 | -| 交换管理 | -| 进程虚拟地址空间 | -| 共享内存虚拟文件系统 | -| 内存溢出管理 | - - -#2 参考内容 -------- - -| 链接 | -|:-------:| -| [内存管理(一)内存模型之Node](http://biancheng.dnbcw.info/linux/387391.html) | -| [Linux 内存管理 重要结构体](http://blog.chinaunix.net/uid-26009500-id-3078986.html) | -| [Bootmem机制](http://blog.csdn.net/samssm/article/details/25064897) | -| [Linux-2.6.32 NUMA架构之内存和调度](http://www.cnblogs.com/zhenjing/archive/2012/03/21/linux_numa.html) | -| [Linux 用户空间与内核空间——高端内存详解](http://blog.csdn.net/tommy_wxie/article/details/17122923) | -| [探索 Linux 内存模型](http://www.ibm.com/developerworks/cn/linux/l-memmod/) | -| [Linux内存管理](http://blog.chinaunix.net/uid/21718047/cid-151509-list-2.html) | -| [内存管理-之内核内存管理-基于linux3.10](http://blog.csdn.net/shichaog/article/details/45509917) | -| [内存管理(一)](http://www.cnblogs.com/openix/p/3334026.html) | -| [Linux内存管理原理](http://www.cnblogs.com/zhaoyl/p/3695517.html) | -| [第 15 章 内存映射和 DMA](http://www.embeddedlinux.org.cn/ldd3/ch15.html) | -| [ 内存管理(二)struct page ](http://blog.chinaunix.net/uid-30282771-id-5176971.html) | - diff --git a/study/kernel/02-memory/07-pagereclaim/README.md b/study/kernel/02-memory/07-pagereclaim/README.md deleted file mode 100644 index 1a3d0ec..0000000 --- a/study/kernel/02-memory/07-pagereclaim/README.md +++ /dev/null @@ -1,46 +0,0 @@ -服务器体系与共享存储器架构 -======= - -| 日期 | 内核版本 | 架构| 作者 | GitHub| CSDN | -| ------- |:-------:|:-------:|:-------:|:-------:|:-------:| -| 2016-06-14 | [Linux-4.7](http://lxr.free-electrons.com/source/?v=4.7) | X86 & arm | [gatieme](http://blog.csdn.net/gatieme) | [LinuxDeviceDrivers](https://github.com/gatieme/LDD-LinuxDeviceDrivers) | [Linux内存管理](http://blog.csdn.net/gatieme/article/category/6225543) | - - -#1 目录 -------- - -| CSDN | GitHub | -|:-------:|:-------:| -| 描述物理内存 | -| 页表管理 | -| 初始化内存挂历 | -| 物理内存的管理 | -| slab分配器 | - -| 非连续内存分配 | -| 高端内存管理 | -| 页面帧回收 | -| 交换管理 | -| 进程虚拟地址空间 | -| 共享内存虚拟文件系统 | -| 内存溢出管理 | - - -#2 参考内容 -------- - -| 链接 | -|:-------:| -| [内存管理(一)内存模型之Node](http://biancheng.dnbcw.info/linux/387391.html) | -| [Linux 内存管理 重要结构体](http://blog.chinaunix.net/uid-26009500-id-3078986.html) | -| [Bootmem机制](http://blog.csdn.net/samssm/article/details/25064897) | -| [Linux-2.6.32 NUMA架构之内存和调度](http://www.cnblogs.com/zhenjing/archive/2012/03/21/linux_numa.html) | -| [Linux 用户空间与内核空间——高端内存详解](http://blog.csdn.net/tommy_wxie/article/details/17122923) | -| [探索 Linux 内存模型](http://www.ibm.com/developerworks/cn/linux/l-memmod/) | -| [Linux内存管理](http://blog.chinaunix.net/uid/21718047/cid-151509-list-2.html) | -| [内存管理-之内核内存管理-基于linux3.10](http://blog.csdn.net/shichaog/article/details/45509917) | -| [内存管理(一)](http://www.cnblogs.com/openix/p/3334026.html) | -| [Linux内存管理原理](http://www.cnblogs.com/zhaoyl/p/3695517.html) | -| [第 15 章 内存映射和 DMA](http://www.embeddedlinux.org.cn/ldd3/ch15.html) | -| [ 内存管理(二)struct page ](http://blog.chinaunix.net/uid-30282771-id-5176971.html) | - diff --git a/study/kernel/02-memory/08-pageswapping/README.md b/study/kernel/02-memory/08-pageswapping/README.md deleted file mode 100644 index 1a3d0ec..0000000 --- a/study/kernel/02-memory/08-pageswapping/README.md +++ /dev/null @@ -1,46 +0,0 @@ -服务器体系与共享存储器架构 -======= - -| 日期 | 内核版本 | 架构| 作者 | GitHub| CSDN | -| ------- |:-------:|:-------:|:-------:|:-------:|:-------:| -| 2016-06-14 | [Linux-4.7](http://lxr.free-electrons.com/source/?v=4.7) | X86 & arm | [gatieme](http://blog.csdn.net/gatieme) | [LinuxDeviceDrivers](https://github.com/gatieme/LDD-LinuxDeviceDrivers) | [Linux内存管理](http://blog.csdn.net/gatieme/article/category/6225543) | - - -#1 目录 -------- - -| CSDN | GitHub | -|:-------:|:-------:| -| 描述物理内存 | -| 页表管理 | -| 初始化内存挂历 | -| 物理内存的管理 | -| slab分配器 | - -| 非连续内存分配 | -| 高端内存管理 | -| 页面帧回收 | -| 交换管理 | -| 进程虚拟地址空间 | -| 共享内存虚拟文件系统 | -| 内存溢出管理 | - - -#2 参考内容 -------- - -| 链接 | -|:-------:| -| [内存管理(一)内存模型之Node](http://biancheng.dnbcw.info/linux/387391.html) | -| [Linux 内存管理 重要结构体](http://blog.chinaunix.net/uid-26009500-id-3078986.html) | -| [Bootmem机制](http://blog.csdn.net/samssm/article/details/25064897) | -| [Linux-2.6.32 NUMA架构之内存和调度](http://www.cnblogs.com/zhenjing/archive/2012/03/21/linux_numa.html) | -| [Linux 用户空间与内核空间——高端内存详解](http://blog.csdn.net/tommy_wxie/article/details/17122923) | -| [探索 Linux 内存模型](http://www.ibm.com/developerworks/cn/linux/l-memmod/) | -| [Linux内存管理](http://blog.chinaunix.net/uid/21718047/cid-151509-list-2.html) | -| [内存管理-之内核内存管理-基于linux3.10](http://blog.csdn.net/shichaog/article/details/45509917) | -| [内存管理(一)](http://www.cnblogs.com/openix/p/3334026.html) | -| [Linux内存管理原理](http://www.cnblogs.com/zhaoyl/p/3695517.html) | -| [第 15 章 内存映射和 DMA](http://www.embeddedlinux.org.cn/ldd3/ch15.html) | -| [ 内存管理(二)struct page ](http://blog.chinaunix.net/uid-30282771-id-5176971.html) | - diff --git a/study/kernel/03-vmarea/README.md b/study/kernel/03-vmarea/README.md new file mode 100644 index 0000000..d4d3d2e --- /dev/null +++ b/study/kernel/03-vmarea/README.md @@ -0,0 +1,28 @@ +进程虚拟地址空间 +======= + +| 日期 | 内核版本 | 架构| 作者 | GitHub| CSDN | +| ------- |:-------:|:-------:|:-------:|:-------:|:-------:| +| 2016-06-14 | [Linux-4.7](http://lxr.free-electrons.com/source/?v=4.7) | X86 & arm | [gatieme](http://blog.csdn.net/gatieme) | [LinuxDeviceDrivers](https://github.com/gatieme/LDD-LinuxDeviceDrivers) | [Linux内存管理](http://blog.csdn.net/gatieme/article/category/6225543) | + + + +#1 虚拟地址空间 +------- + +用户层进程的虚拟地址空间是Linux的一个重要抽象 : 它向每个运行进程提供了同样的系统视图, 这使得多个进程可以同时运行, 而不会干扰到其他进程内存中的内容. 此外, 它容许使用各种高级的程序设计技术,如内存映射 + +从今天开始, 我将讨论内核是如何实现这些概念的. 这同样需要考察可用物理内存中的页帧与所有的进程虚拟地址空间中的页之间的关联 : **逆向映射(reverse +mapping)* ***技术有助于从虚拟内存页跟踪到对应的物理内存页, 而**缺页处理(page fault handling)**则允许从块设备按需读取数据填充虚拟地址空间 + + +* 每个应用程序都有自身的地址空间,与所有其他应用程序分隔开 + +* 通常在巨大的线性地址空间中,只有很少的段可用于各个用户空间进程,这些段彼此有一定的距离。内核需要一些数据结构,来有效地管理这些(随机)分布的段。 + +* 地址空间只有极小的一部分与物理内存页直接关联。不经常使用的部分,则仅当必要时与页帧关联. + +* 内核信任自身,但无法信任用户进程。因此,各个操作用户地址空间的操作都伴随有各种检查,以确保程序的权限不会超出应有的限制,进而危及系统的稳定性和安全性. + +* fork-exec模型在UNIX操作系统下用于产生新进程. 如果实现得较为粗劣, 该模型的功能并不强大。因此内核必须借助于一些技巧,来尽可能高效地管理用户地址空间 +