Kernel memory is managed in a fairly straightforward way. It is not demand-paged, meaning that, for every allocation using kmalloc()
or similar function, there is real physical memory. Kernel memory is never discarded or paged out.
Some architectures show a summary of the memory mapping at boot time in the kernel log messages. This trace is taken from a 32-bit ARM device (a BeagleBone Black):
Memory: 511MB = 511MB total Memory: 505980k/505980k available, 18308k reserved, 0K highmem Virtual kernel memory layout: vector : 0xffff0000 - 0xffff1000 ( 4 kB) fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB) vmalloc : 0xe0800000 - 0xff000000 ( 488 MB) lowmem : 0xc0000000 - 0xe0000000 ( 512 MB) pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB) modules : 0xbf800000 - 0xbfe00000 ( 6 MB) .text : 0xc0008000 - 0xc0763c90 (7536 kB) .init : 0xc0764000 - 0xc079f700 ( 238 kB) .data : 0xc07a0000 - 0xc0827240 ( 541 kB) .bss : 0xc0827240 - 0xc089e940 ( 478 kB)
The figure of 505980 KiB available is the amount of free memory the kernel sees when it begins execution but before it begins making dynamic allocations.
Consumers of kernel-space memory include the following:
.text
, .init
, .data
, and .bss
. The .init
segment is freed once the kernel has completed initialization.kmalloc()
. They come from the region marked lowmem
.vmalloc()
, usually for larger chunks of memory than is available through kmalloc()
. These are in the vmalloc area./proc/iomem
. These come from the vmalloc area but since they are mapped to physical memory that is outside of main system memory, they do not take any real memory.Unfortunately, there isn't a complete answer to that question, but what follows is as close as we can get.
Firstly, you can see the memory taken up by the kernel code and data in the kernel log shown previously, or you can use the size
command, as follows:
$ arm-poky-linux-gnueabi-size vmlinux text data bss dec hex filename 9013448 796868 8428144 18238460 1164bfc vmlinux
Usually, the size is small when compared to the total amount of memory. If that is not the case, you need to look through the kernel configuration and remove those components that you don't need. There is an ongoing effort to allow small kernels to be built: search for Linux-tiny or Linux Kernel Tinification. There is a project page for the latter at https://tiny.wiki.kernel.org/.
You can get more information about memory usage by reading /proc/meminfo
:
# cat /proc/meminfo MemTotal: 509016 kB MemFree: 410680 kB Buffers: 1720 kB Cached: 25132 kB SwapCached: 0 kB Active: 74880 kB Inactive: 3224 kB Active(anon): 51344 kB Inactive(anon): 1372 kB Active(file): 23536 kB Inactive(file): 1852 kB Unevictable: 0 kB Mlocked: 0 kB HighTotal: 0 kB HighFree: 0 kB LowTotal: 509016 kB LowFree: 410680 kB SwapTotal: 0 kB SwapFree: 0 kB Dirty: 16 kB Writeback: 0 kB AnonPages: 51248 kB Mapped: 24376 kB Shmem: 1452 kB Slab: 11292 kB SReclaimable: 5164 kB SUnreclaim: 6128 kB KernelStack: 1832 kB PageTables: 1540 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 254508 kB Committed_AS: 734936 kB VmallocTotal: 499712 kB VmallocUsed: 29576 kB VmallocChunk: 389116 kB
There is a description of each of these fields in the man page for proc(5)
. The kernel memory usage is the sum of:
vmalloc()
In the case of slab allocations, you can get more information by reading/proc/slabinfo
. Similarly, there is a breakdown of allocations in /proc/vmallocinfo
for the vmalloc area. In both cases, you need detailed knowledge of the kernel and its subsystems to see exactly which subsystem is making the allocations and why, which is beyond the scope of this discussion.
With modules, you can use lsmod
to find out the memory space taken up by the code and data:
# lsmod Module Size Used by g_multi 47670 2 libcomposite 14299 1 g_multi mt7601Usta 601404 0
That leaves the low level allocations of which there is no record, and which prevent us from generating an accurate account of kernel space memory usage. This will appear as missing memory when we add up all the kernel and user space allocations that we know about.