Why does Linux show both more and less memory than I physically have installed?

10,806

You should read the dmesg values "Memory Akb/Bkb available" as:

There is A available for use right now, and the system's highest page frame number multiplied by the page size is B.

This is from arch/x86/mm/init_64.c:

printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
                 "%ldk absent, %ldk reserved, %ldk data, %ldk init)\n",
                 nr_free_pages() << (PAGE_SHIFT-10),
                 max_pfn << (PAGE_SHIFT-10),
                 codesize >> 10,
                 absent_pages << (PAGE_SHIFT-10),
                 reservedpages << (PAGE_SHIFT-10),
                 datasize >> 10,
                 initsize >> 10);

nr_free_pages() returns the amount of physical memory, managed by the kernel, that is not currently in use. max_pfn is the highest page frame number (the PAGE_SHIFT shift converts that to kb). The highest page frame number can be (much) higher than what you could expect - the memory mapping done by the BIOS can contain holes.
How much these holes take up is tracked by the absent_pages variable, displayed as kB absent. This should explain most of the difference between the second number in the "available" output and your actual, installed RAM.

You can grep for BIOS-e820 in dmesg to "see" these holes. The memory map is displayed there (right at the top of dmesg output after boot). You should be able to see at what physical addresses you have real, usable RAM.
(Other x86 quirks and reserved memory areas probably account for the rest - I don't know the details there.)

MemTotal in /proc/meminfo indicates RAM available for use. Right at the end of the boot sequence, the kernel frees init data it doesn't need any more, so the value reported in /proc/meminfo could be a bit higher than what the kernel prints out during the initial parts of the boot sequence.

(meminfo uses indirectly totalram_pages for that display. For x86_64, this is calculated in arch/x86/mm/init_64.c too via free_all_bootmem() which itself is in mm/bootmem.c for non-NUMA kernels.)

Share:
10,806

Related videos on Youtube

Robin Green
Author by

Robin Green

Updated on September 18, 2022

Comments

  • Robin Green
    Robin Green over 1 year

    I know about swap - this question isn't about that. In dmesg, the Linux (x86-64) kernel tells me this about how much memory I have:

    [    0.000000] Memory: 3890880k/4915200k available (6073k kernel code, 861160k absent, 163160k reserved, 5015k data, 1596k init)
    

    cat /proc/meminfo tells me that I have

    MemTotal:        3910472 kB
    

    And by my calculations, I think I should have exactly 4*1024*1024=4194304k RAM. Which is way smaller than the second figure in the dmesg line above!

    What's with all these different figures?

    By the way, uname -a outputs:

    Linux pavilion 3.2.2-1.fc16.x86_64 #1 SMP Thu Jan 26 03:21:58 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux