Linux内核Vmalloc区域大小的计算

以前自己跟着内核内存管理的一些宏定义画过内存分布图
比如VMALLOC_START, VMALLOC_END, FIXADDR_START等等
一直以为这些值在实际内核中多多少少会有误差,没想到前几天看了一下
居然完全吻合。

来试着计算一下Vmalloc的总大小,为了便于计算我们认为1G的内核空间从0地址开始。
首先我的物理内存超过了896M,因此high_memory就是896M
其上是8M的空洞用于捕捉越界的内存访问,于是VMALLOC_START在896M+8M = 904M

下面再来计算VMALLOC_END。
最顶上是一个内存空洞,然后是固定映射的区域,这个区域的分布可以参考下面这个枚举
enum fixed_addresses {
    FIX_HOLE,
    FIX_VDSO,
    FIX_DBGP_BASE,
    FIX_EARLYCON_MEM_BASE,
#ifdef CONFIG_X86_LOCAL_APIC
    FIX_APIC_BASE,    /* local (CPU) APIC) -- required for SMP or not */
#endif
#ifdef CONFIG_X86_IO_APIC
    FIX_IO_APIC_BASE_0,
    FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
#endif
#ifdef CONFIG_X86_VISWS_APIC
    FIX_CO_CPU,    /* Cobalt timer */
    FIX_CO_APIC,    /* Cobalt APIC Redirection Table */
    FIX_LI_PCIA,    /* Lithium PCI Bridge A */
    FIX_LI_PCIB,    /* Lithium PCI Bridge B */
#endif
#ifdef CONFIG_X86_F00F_BUG
    FIX_F00F_IDT,    /* Virtual mapping for IDT */
#endif
#ifdef CONFIG_X86_CYCLONE_TIMER
    FIX_CYCLONE_TIMER, /*cyclone timer register*/
#endif
    FIX_KMAP_BEGIN,    /* reserved pte's for temporary kernel mappings */
    FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
#ifdef CONFIG_PCI_MMCONFIG
    FIX_PCIE_MCFG,
#endif
#ifdef CONFIG_PARAVIRT
    FIX_PARAVIRT_BOOTMAP,
#endif
    __end_of_permanent_fixed_addresses,
    /*
     * 256 temporary boot-time mappings, used by early_ioremap(),
     * before ioremap() is functional.
     *
     * We round it up to the next 256 pages boundary so that we
     * can have a single pgd entry and a single pte table:
     */
#define NR_FIX_BTMAPS        64
#define FIX_BTMAPS_SLOTS    4
    FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
            (__end_of_permanent_fixed_addresses & 255),
    FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
    FIX_WP_TEST,
#ifdef CONFIG_ACPI
    FIX_ACPI_BEGIN,
    FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
#endif
#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
    FIX_OHCI1394_BASE,
#endif
    __end_of_fixed_addresses
};
其中每一个枚举量代表一个或一些页面,
除了NR_CPUS我们取1之外,其他的全都取最大值也不超过1K个页面
也就是说固定映射最多不到4M

再下面就是永久映射区域,先看看永久内核映射的起始地址定义
#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE * (LAST_PKMAP + 1)) & PMD_MASK)
也就是说永久内核映射的起始地址是在固定内核映射-4M之下4M对齐的位置,
前面已经看到固定内核映射是小于4M的,因此永久内核映射的起始地址就在1G-8M的位置
在这里占用一个PMD,对于x86来说也就是占用4M的空间

再往下就是VMALLOC区了,看定义
# define VMALLOC_END    (PKMAP_BASE - 2 * PAGE_SIZE)
就是说永久内核映射起始地址再往下2个页面就是VMALLOC_END了
因此VMALLOC_END = 1G-8M-2*4K

由此可得总的vmalloc空间为
  VMALLOC_END - VMALLOC_START
= 1G-8M-2*4K - 904M
= 1048576k - 8192k - 8k - 925696k
= 114680k

现在看看
cat /proc/meminfo |grep VmallocTotal
是不是114680k?

你可能感兴趣的:(timer,IO,table,UP,X86,linux内核)