《Linux内核设计与实现》读书笔记整理(2)


内存管理:

  • 物理页是内存管理的基本单位。页再组成区,区的划分是为了管理页而采取的逻辑分组。内存管理单元(MMU)是一个管理内存并把虚拟地址转换为物理地址的硬件。内存分配机制:页分配器和slab分配器
  • 内核通过函数alloc_pages()分配页并使用page_address()将页转换成逻辑地址。
  • 内核通过函数kmalloc()和vmalloc()获得内核内存,前者确保页在物理地址上是连续的,当然虚拟地址也是连续的;后者内存虚拟地址是连续的,而物理地址不需要连续,这也是用户空间分配内存的工作方式。
  • vmalloc()把不连续的物理页转换为虚拟地址空间上连续的页,需要建立页表项,性能和kmalloc()相比有一定的性能损失。
  • slab即通用数据结构缓存层。slab层把不同的对象划分为高速缓存组,每种对象类型对应一个高速缓存组。高速缓存又被划分为多个slab,slab由一个或多个物理上连续的页组成。被缓存的数据结构存储在各个slab中。例如进程描述符(task_struct)和索引结点(struct inode)都会被缓存到slab中。

虚拟文件系统和块I/O层:

  • 内核在底层文件系统接口上建立了一个抽象层。
  • 索引结点(inode)是一个存储文件元数据(访问控制权限、大小、拥有者、创建时间等信息)的数据结构。
  • 文件系统的控制信息存储在超级块中,是一种包含文件系统信息的系统结构。而文件(也包括目录)信息按照索引结点形式存储在单独的块中。
  • 文件对象是已打开的文件在内存中的表示。文件对象由file_struct结构体表示,被包含在一个数组中,并关联到进程描述符的files属性下。
  • 能够随机访问固定大小数据片的硬件设备称作块设备。块设备中最小的寻址单位是扇区。最小逻辑可寻址单元是块,且不能超过页(内存管理的基本单位)的大小。
  • 内核中块I/O操作的基本容器由bio结构体表示,每个块I/O请求都通过一个bio结构体表示。
  • 块设备将挂起的块I/O请求保存在请求队列中。
  • 在内核中负责提交I/O请求的子系统称为I/O调度程序。I/O调度程序通过将请求队列中挂起的请求合并和排序来完成I/O资源分配。
  • 磁盘头向一个方向移动,可缩短所有请求的磁盘寻址时间,这种调度方式称为电梯调度。
  • linus电梯调度程序会带来写-饥饿-读(writes-starving-reads)的问题。一般写操作为异步,读操作为同步(阻塞),所以读操作响应时间对系统性能来说非常重要。
  • 主要的几种调度算法:
    • 最后期限I/O调度:每个I/O请求都有一个超时时间。此算法维护三个队列,一个是正常的合并排序队列,另外两个分别是读/写请求的队列。如果在读/写请求队列头发现请求超时(读超时500ms,写超时5s),就从队列中提取请求进行服务。此算法试图保证在超期的情况下可优先获得服务,防止请求饥饿现象的发生,并照顾了读操作。
    • 预测I/O调度:和最后期限调度对比,主要增加了预测启发能力。读请求处理后会等待一小段时间(6ms),此时进程提交的其它相邻位置的读请求都会立刻得到处理。在等待时间结束之后,再恢复执行剩下的请求。调度程序会跟踪并统计每个应用程序的块I/O操作的行为,以便提升预测准确度。
    • 完全公平的排队I/O调度(Complete Fair Queuing):CFQ将I/O请求根据发起的进程分类后归于不同的队列中,从每个队列中选取特定的请求数,并以时间片轮转调度队列。可提供进程级的公平性。
    • 空操作的I/O调度:不进行排序,也不预测,只维护一个队列并进行合并操作。主要应用场景是闪存卡等快速的随机访问设备。

进程地址空间:

  • 用户空间中进程的内存称为进程地址空间。linux采用虚拟内存技术,进程之间以虚拟方式共享内存。对一个进程而言,它好像可以访问到整个系统的所有物理内存。通常情况下,每个进程都有唯一的平坦地址空间,一个进程的地址空间与另一个进程的地址空间即使有相同的内存地址,实际上也互不相关。
  • 进程使用内存描述符表示进程地址空间,数据结构为mm_struct,进程描述符task_struct结构体的mm域指向着它。
  • mm_struct结构体的域mmap(链表)和mm_rb(红黑树)这两个不同的数据结构都描述了当前进程的全部内存区域,它们包含完全相同的vm_area_struct结构体(即描述内存区域的结构体)的指针,只是组织方法不同。
  • 程序访问一个虚拟地址时,首先必须将虚拟地址转换为物理地址。地址的转换工作需要通过查询页表来完成。

页高速缓存和页回写:

  • 页高速缓存即内核实现的磁盘缓存。页高速缓存由内存中的物理页面组成,内容对应磁盘上的物理块。
  • 页回写:写操作时对缓存采取的一种策略。写操作会被直接写入到缓存中,并将高速缓存中被写入的页标记成“脏”,加入到脏页链表中,再由flusher回写进程周期性将链表的脏页写回到磁盘,最后清理脏页标识。
  • 页高速缓存回收策略使用的是双链表LRU。
  • 页高速缓存的结构体是address_space(这个命名不太好),一个文件可以被多个进程的多个vm_area_struct标识,但是该文件只能有一个address_space数据结构,也就是说文件的虚拟地址可以有多个,但只能在物理内存里有一份。

Published

Author

Levin

Category

Unix/Linux

Tags

linux
Disqus loading now...