LINUX C 内存管理(上)

6.1 内存管理中的基本概念

1、页:内核把物理页作为内存管理的基本单位,尽管处理器的最小可寻址的单位是字节,但是内存管理单元(MMU)通常以页为单位进行处理。大多数32位体系结构的处理器支持4KB的页,内核用struct page 结构表示系统的物理页,页的拥有者可能是用户控件进程、动态分配的内核数据、静态内核代码或高速缓存等

 

2、区:有些页位于内存特定的物理地址上,所以不能将其用于一些特定任务,故内核把页分成不同的区,分别是ZONE_DMAZONE_DMA32ZONE_NORMALZONE_HIGHMEM(高端内存,其中的页并不能永久地映射到内核地址空间)。每个区用struct zone结构体表示,不是所有的体系结构都定义了全部区,如X86-64没有ZONE_HIGHMEM区。

 

6.2申请内存的几种方法

当只需要一两页连续物理页时,使用低级的页函数更有效:

Alloc_page (返回页结构指针)+ page_address = _get_free_pages(返回逻辑地址指针)

还可以用kmalloc函数,传递给这个函数的常用标志GFP_KERNELGPF_ATOMIC,其中:

l GPF_ATOMIC用在中断处理程序、下半部、持有自旋锁以及其他不能 睡眠的地方。

l GPF_KERNEL是常用的分配方法,可能会阻塞,在睡眠安全时用在进 程上下文。

l GPF_NOIO这种分配可以阻塞,但不会启动磁盘I/O

 

如果不需要连续的物理地址时,只要连续的物理地址,可以使用vmalloc函数,但是物理地址不不连续性,导致通过vmalloc获得的页必须一个一个地进行映射,这就导致比直接内存映射大得多的TLB(用来缓存虚拟地址到物理地址的映射关系)抖动,在迫不得已时不应使用该函数。

 

如果需要从高端内存进行分配,由于高端内存(物理地址高于896MB)中的页被映射到3~4GB,所以应该使用alloc_pages获得页指针,而不能用_get_free_pagekmalloc,因为这两个函数返回的都是逻辑地址,而不是page结构。

 

使用KMAP函数可以将获得的页永久映射到内核地址空间,还可以睡眠,只能在上下文使用,因为允许永久映射的数量是有限的,当不需要高端内存时,应该使用kunmap解除映射。

 

如果需要获得的页临时映射到内核地址空间,可以使用kmap_atomic函数,他不能睡眠,可以用在中断处理程序中,同样释放可用kunmap_atomic函数。

如果需要创建和撤销很多大的数据结构,就需要考虑建立slab高速缓存,它能极大提高对象分配和回收的性能。Slab层不是频繁地分派和释放内存,而是把事先分配好的对象存放到高速缓存中,需要一块新的内存来存放数据结构时,slab层一般无需另外区分配内存,只需要从高速缓存中得到这个对象。

 

Slab层把不同的对象分为高速缓存组,每个高速缓存中存放不同类型的对象,每个高速缓存中又被划分为多个slabslab由一个或多个物理上连续的页组成,每个slab处于三种状态之一:满、部分满或空。当内核的某一部分需要一个新的对象时,先从部分满的slab中进行分配,如果没有部分满的slab,就从空的slab中进行分配,如果没有空的slab,就要创建一个slab,这样能减少碎片,每一个高速缓存用struct kmem_cache结构体表示,同时slab也有struct slab结构体。

 

6.3内核栈

每个进程都有两个页的内核栈,32位和64位体系结构处理器的页面大小分别是4KB8KB,所以内核栈的大小分别为8KB16KB。由于连续两页有时难以寻找到,所以引入单页内核栈。当使用一个页面的内核栈时,中断处理程序就不放在栈里,为每一个进程提供一个用于中断处理程序的栈,即中断栈,这样中断处理程序不用再和被中断进程共享一个内核栈。

 

中断处理程序和被中断的进程共享一个栈,不过当1页栈被激活,中断处理程序就获得自己的栈。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值