内核学习之二: Linux内存机制探秘

内存管理分两类:

一、对物理内存的管理:对实际物理内存的管理;

二、对虚拟内存的管理:即对特定处理器体系架构上虚拟地址空间的管理; 

 

linux系统为了使代码有最大程度的兼容性,在物理内存管理引入下面概念:

内存节点(node);

内存区域(zone);

内存页(page);

 

2.1对物理内存的管理:

 

对物理内存的管理分2部分:

 

 

 

内存节点:node

UMA系统:只有一个节点;

NUMA系统:多个节点的链表:struct pglist_data;

 

 

 内存区域:struct zone;

是对单个内存节点中的概念,内存区域有不同的类型:

enum zone_type {

ZONE_DMA,            /*arm体系上,大小可变;*/

ZONE_DMA32,       /*x86体系用*/

ZONE_NORMAL,   /*常规区域*/

ZONE_HIGHMEM, /*高端区域,该区域无法从内核虚拟地址直接作线性映射,必须做页映射。

ZONE_MOVABLE,

__MAX_NR_ZONES

}

 

文件位置:linux/mmzone.h

Struct zone{

 Spinlock_t      lock;

Unsigned long    free_pages;

Unsigned long    free_min;

Unsigned long    free_low;

Unsigned long    free_high;

Unsigned long    protection[MAX_NR_ZONES];

Spinlock_t       lru_lock;

Struct list_head   active_list;

Strcut list_head   inactive_list;

Unsigned long    nr_scan_active;

Unsigned long    nr_scan_inactive;

Unsigned long    nr_active;

Unsigned long    nr_inactive;

Int              all_unreclainable;

Unsigned long                  page_scanned;

Int                     temp_priority;

Int                     prev_priority;

Struct free_area           free_area[MAX_ORDER];

Wait_queue_head_t       *wait_table;

Unsigned long                  wait_table_size;

Unsigned long                  wait_table_bit;

Struct per_cpu_pageset   pageset[NR_CPUS];

Struct pglist_data         *zone_pgdat;

Struct page              *zone_mem_map;

Unsigned long          zone_start_pfn;

Char                  *name;

Unsigned long          spanned_pages;

Unsigned long         present_pages;

}

 

     这个结构很大,但系统只有三个区,因此也只有三个这样的结构。

Lock域是自旋锁,防止该结构被并发访问。这个域只保护结构,不保护驻留在这个区中的所有页。没有锁可以锁住单个页,但部分内核可锁住页中驻留的数据。

Free_pages域是这个区中空闲的页数,内核尽可能保证(通过交换)pages_min个空闲页可用。

Name域是一个以null结束的字符串,表示这个区的名字,内核启动时初始化这个值,代码在mm/page_alloc.c中,三个区的名字:“DMA”“Normal”和HighMem。

 

2.1 内存分页:

物理内存的最小单位,也叫页帧(page frame)。

页的大小取决于系统中的内存管理单元MMU:

32位:4k/页;
64位:8k/页;

 

定义:

linux/mm.h:

Struct page {

Page_flags_t          flags;           页状态:是否脏,是否被锁定等32种;()

Atomic_t         _count;      页引用计数;计数为0,则可被申请;

Atomic_t         _mapcount;  

Unsigned long     private;

Struct address_space   *mapping;

Pgoff_t           index;

Struct list_head    lru;

Void             *virtual;      页的虚拟地址。对高端内存,该值为null,需要时动态映射这些页;

};
Page是和物理页对应,它描述物理内存本身,并不描述其中的数据;

系统用一个全局变量struct page *mem_map来存放所有物理页对象指针。

 

 

2.2 内存page接口:
 

申请接口:

Alloc_page(gfp_mask)         只分一个页,返回指向页结构的指针;

Alloc_pages(gfp_mask,order)   只分2 (order次方)页,返回指向第一页结构的指针;

_get_free_page(gfp_mask)     只分一个页,返回指向逻辑地址的指针;

__get_free_pages(gfp_mask,order)只分2 (order次方)页,返回指向第一页逻辑地址的指针;

Get_zeroed_page(gfp_mask)    只分一页,让其内容填0,返回指向其逻辑地址的指针;

 

 

           因为mem_map中每一个struct page对象和物理页面一一对应,这使得mem_map也分三个区,Linux初始化期间,会将虚拟地址空间的页面直接映射区作线性映射到ZONE_DMA和ZONE_NORMAL,如果页面分配器分配的页落在这两个zone中,那么对应的内核虚拟地址到物理地址的映射的页目录表项已经建立,线性映射就是虚拟地址和物理地址之间只有一个差值(PAGE_OFFSET= 0xc0000000);

         如果所分配的页面在ZONE_HIGH中,那么内核这时还没有对该页面的映射,所有页面分配器的调用者(如设备驱动程序)需要在内核虚拟地址空间的动态映射区分配一个虚拟地址,然后映射到该物理页面上,内核提供了接口函数。

 

2.3 gfp_mask :控制分配行为的掩码,并可以告诉内核在哪个zone中分配物理页面。

<include/linux/gpf.h>        以下定义供内核自己用

#define __GFP_DMA                ((__force gfp_t)0x01u)

#define __GFP_HIGHMEM     ((__force gfp_t)0x02u)

.......

<include /linux/gfp.h>      以下定义供驱动程序用

#define  GFP_ATOMIC      (__GFP_HIGH)

#define  GFP_KERNEL     (__GFP_WAIT|__FPG_IO|__GFP__FS)

 

GFP_ATOMIC:

         内核模块中最常使用的掩码之一,用于原子分配,所以它是不带__GFP_WAIT的。此掩码告诉分配器,在分配页面时候,绝对不能中断当前进程或者把当前进程移出调度器。必要的情况下可以使用仅限紧急情况使用的保留内存页。

        在驱动程序中,一般在中断处理例程或非进程上下文的代码中使用GFP_ATOMIC掩码进行内存分配,因为这两种情况下分配必须保证当前进程不能睡眠。

GFP_KERNEL:

        内核模块中最常用的掩码之一,可能导致当前进程进入睡眠状态。

GFP_USET:

       用于为用户空间分配页,也可能引起进程休眠。

GFP_NOIO

GFP_NOFS

      都带有__GFP_WAIT,因此可以被中断,前者分配中禁止io,后者禁止文件系统函数调用;

GFP_HIGHUSET

       对GFP_USET的扩展,可以使用非线性映射的高端内存;

GFP_DMA

      只能在DMA区域分配空闲的物理页面;

 

 

 

 

 

 

 

 

 

 

 

 

 

一、             以字节为单位的分配接口:

Linux/slab.h:

Kmalloc()得到以字节为单位的内核内存,物理上是连续的;

Kfree()

 

Vmalloc()   得到以字节为单位的内核内存,虚拟地址是连续的,物理上不一定是连续的;

Vfree ()

 

五、         slab层:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值