Chapter3:MemoryManagement
intended for basic data structures that are needed throughout kernel run time and are therefore never
relinquished.
The Slab Allocator
The bootmem allocator must be disabled once system initialization has progressed so far that the buddy
system allocator can assume responsibility for memory management; after all, memory cannot be man-
aged by two allocators at the same time. Disabling is done byfree_all_bootmemon UMA systems and
byfree_all_bootmem_nodeon NUMA systems. Both need to be invoked by the architecture-specific
initialization code after the buddy system has been set up.
The page bitmap of the bootmem allocator is first scanned, and every unused page is freed. The interface
to the buddy system is the__free_pages_bootmemfunction that is invoked for each freed page. The
function relies internally on the standard function__free_page. It enables the pages to be incorporated
in the data structures of the buddy system, where they are managed as free pages and are available for
allocation.
Once the page bitmap has been fully scanned, the memory space it occupies must also be removed.
Thereafter, only the buddy system can be used for memory allocation.
Releasing InitializationData
Many kernel code chunks and data tables are needed only during the system initialization phase. For
example, it is not necessary to keep data structure initialization routines in kernel memory for per-
manently linked drivers. They are no longer needed once the structures have been set up. Similarly,
hardware databases that drivers need to detect their devices are no longer required once the associated
devices have been identified.^17
The kernel provides two ‘‘attributes‘‘ (__initand__initcall) to label initialization functions and
data. These must be placed before the function or data declarations. For instance, the probing rou-
tine of the (fictitious...) network card HyperHopper2000 is no longer used once the system has been
initialized.
int __init hyper_hopper_probe(struct net_device *dev)
The__initattribute is inserted between the return type and name in the function declaration.
Data sections can likewise be labeled as initialization data. For example, the fictitious network card driver
requires a few strings in the system initialization phase only; thereafter the strings can be discarded.
static char search_msg[] initdata = "%s: Desperately looking for HyperHopper at address %x...";
static char stilllooking_msg[] __initdata = "still searching...";
static char found_msg[] initdata = "found.\n";
static char notfound_msg[] __initdata = "not found (reason = %d)\n";
static char couldnot_msg[] __initdata = "%s: HyperHopper not found\n";
__initand__initdatacannot be implemented using normal C means so that the kernel once again
has to resort to special GNU C compiler statements. The general idea behind the implementation of
(^17) At least for compiled-in data and devices that are not hotpluggable. If devices are added to the system dynamically, the data tables
cannot, of course, be discarded as they may be required later.