内核和进程的内存管理,内核从buddy到alloc到slab到kmalloc,内核的内核栈和中断处理程序栈,进程的虚拟内存到页表

内核中的内存管理

内核把物理页作为内存管理的基本单位,尽管处理器最小寻址单位为字,但是MMU(管理内存并且把虚拟地址转换为物理地址的硬件)通常以页为单位进行处理。

每个物理页面都由一个相应的 struct page 结构来表示,4GB的内存大约有20MB的空间是存储每个物理页的struct page。

struct page {
    unsigned long flags;            // 页面状态标志
    atomic_t _count;                // 页面引用计数
    atomic_t _mapcount;             // 页面映射计数
    unsigned long private;          // 用于私有数据
    struct address_space *mapping;  // 与页面关联的地址空间
    pgoff_t index;                  // 页面在地址空间中的偏移量
    struct list_head lru;           // LRU 链表中的节点
    void *virtual;                  // 虚拟地址
};

通过mapping字段可以获取到与页面关联的地址空间对象,拥有者可以是用户空间进程,动态分配的内核数据,静态内核代码和页高速缓存等。

struct address_space {
    const struct address_space_operations *a_ops;
    struct inode *host; // 关联的对象,通常是 inode 结构,查看 inode 结构以获取文件的详细信息
};

内核把物理页划分为不同的区(zone),只是逻辑上的划分。
将内存划分为区,形成不同的内存池。
在一些体系结构中,有些内存不能DMA(Direct Memory Access).
有三种分区(常见的):

  • ZONE_DMA:可以DMA的内存区域。
  • ZONE_NORMAL:可以正常映射的页。
  • ZONE_HIGHEM:"高位内存“,其中的页不能永久地映射到地址空间。

使用page_struct来管理页

分页子系统(Page Allocator)使用struct page来维护空闲页的列表、管理页面的状态等。在内核的其他部分,比如文件系统、内存映射子系统等,也会使用struct page来管理页面。

伙伴系统(Buddy System)是一种常见的物理内存管理算法。Buddy Allocator用于管理物理页的分配和释放,而Slab Allocator则用于高效管理内核中的对象缓存。

slab系统和buddy系统和分配内存底层函数的关系

内核和进程的内存管理,内核从buddy到alloc到slab到kmalloc,内核的内核栈和中断处理程序栈,进程的虚拟内存到页表_第1张图片

alloc_pages等获得内存的函数是基于buddy系统,而slab系统又是基于分配内存的函数,kmalloc()又是基于slab系统的(使用了一组通用高速缓存)。

伙伴系统(Buddy System):用于内核的物理内存管理

管理物理帧,为了减少碎片。保持块的大小确定,alloc_pages就是使用buddy system,_get_free_pages 函数是基于伙伴系统的实现的。
维持11个链表,代表不同大小的块(页数不同)。

  • 链表 0(大小为 2^0 = 1个页)
  • 链表 1(大小为 2^1 = 2个页)
  • 链表 2(大小为 2^2 = 4个页)
分配内存:

当需要分配一块大小为 2^k 的内存时,伙伴系统首先检查对应大小的内存块链表。如果找到了一个空闲的块,就将其分配出去。
如果对应大小的链表中没有可用的块,系统会向更大一级的链表查找,直到找到一个可用的块。这个找到的块会被一分为二,其中一个分配给请求者,而另一个则继续放入对应大小的链表。

释放内存:

当一块内存被释放时,伙伴系统会检查其相邻的块是否也是空闲的。如果是,它们将被合并成一个更大的块,并将该块插入到对应大小的链表中。
这个过程会一直进行,直到找到一个不是空闲的伙伴块或者达到最大的块大小。
这种方式可以有效地减少外部碎片,因为当内存被释放时,相邻的空闲块很有可能会被合并成一个更大的块,使得更大的内存块变得可用。

需要注意的是,伙伴系统中通常会有多个链表,每个链表对应不同大小的块。

内存分配和释放的函数

内存分配的底层函数

struct page *alloc_pages(gfp_t gfp_mask,unsigned int order);

该函数分配2的order次方个连续的物理页,并返回一个指针,指向第一个page结构体。

alloc_pages函数与伙伴系统紧密相关,因为它通常是由伙伴系统实现的,用于在物理内存中分配一定数量的连续页面。

void *page_address(struct page * page)

将物理页转换为逻辑地址

unsigned long _get_free_pages(gfp_t gft_mask,unsigned int order);

返回一个指针,指向物理页所在的逻辑地址,而不是struct_page

unsigned long get_zeroed_page(unsigned int gfp_mask);

这个函数和_get_free_pages()实现方式相同,只是将分配好的页都填充为了0.

内存释放的底层函数

void _free_pages(struct page* page,unsigned int order)
free_pages(unsigned long addr,unsigned int order);

void free page(unsigned long addr);

以字节为单位的分配和释放:kmalloc()和kfree();vmalloc()和vfree();

void* kmalloc(size_t size,gfp_t flags)

这个函数返回一个指向内存块的指针,其内存块至少要有size大小,所分配的内存区是物理上连续的

gfp_mask标志
行为修饰符标识内核该如何分配所需内存。

void vmalloc(unsigned long size)

返回的内存物理地址上不是连续的,使用较少。

Slab分配器

buddy无法分配字节大小的内存块,slab分配器就应运而生了,专为小内存分配而生。slab分配器分配内存以Byte为单位。但是slab分配器并没有脱离伙伴系统,而是基于伙伴系统分配的大内存进一步细分成小内存分配。

内核和进程的内存管理,内核从buddy到alloc到slab到kmalloc,内核的内核栈和中断处理程序栈,进程的虚拟内存到页表_第2张图片

分配和释放数据结构的缓存链表。
空闲链表(即图中的高速缓存)包含可供使用的,已经分配好的数据结构块,当使用时就从链表中取出一个。
图中的对象指的是固定大小的内存块(即被缓存的数据结构)。
我们可以创建任何数据结构的高速缓存链表。

slab管理的内容

Slab Allocator通常用于管理内核中的对象缓存,其中缓存的对象的大小是固定的。这些对象缓存可以包括一系列常用的内核数据结构,以提高对这些数据结构的分配和释放的效率。以下是一些常见的内核数据结构,通常由Slab Allocator来管理:

进程控制块(Process Control Block,PCB):

每个运行的进程在内核中都有一个对应的 PCB,包含了进程的各种信息,如进程状态、寄存器值、进程ID等。

文件结构体(File Structure):

内核中管理文件的结构体,包含有关文件的信息,如文件描述符、文件位置指针、文件状态等。

网络套接字结构体:

用于表示网络套接字的结构体,包含有关套接字的信息,如协议、端口号、连接状态等。

页表项(Page Table Entry):

用于虚拟内存管理的页表项,包含有关虚拟地址到物理地址的映射信息。

目录项(Directory Entry):

用于文件系统管理的目录项,包含有关文件或子目录的信息,如文件名、文件类型、文件大小等。

缓存块结构体:

用于文件系统缓存的数据块结构体,包含文件数据、索引节点等信息。

内核栈

每个进程的内核栈小而且固定。总的来说,内核栈为一页或者两页。

中断处理程序栈

中断栈为每个进程提供一个用于中断处理程序的栈

用户的内存空间分配

创建进程的虚拟地址空间分配

操作系统会为每个用户进程提供一个虚拟地址空间,这个虚拟地址空间通常是连续的、从0开始的地址范围。具体的大小和布局取决于操作系统和硬件架构。

操作系统会为用户进程的虚拟地址空间建立页表,用于将虚拟地址映射到物理地址。

这个过程涉及到虚拟地址的划分,例如将虚拟地址空间划分为代码段、数据段、栈等不同的区域。

懒加载: 初始时,并不是所有的虚拟地址空间都会被立即映射到物理内存中。部分页面可能是“懒加载”的,只有在访问到相应的虚拟地址时,才会触发实际的物理内存分配和映射。

内存分配: 当用户进程需要分配内存时,通常会使用用户空间的内存分配函数(例如 malloc、calloc、brk、mmap 等),而这些函数会在用户空间实现内存管理。这些函数可能采用不同的算法和数据结构来管理用户空间的堆内存。

你可能感兴趣的:(Linux,linux)