Memory issues in Linux


This articles talks about issues in using the memory in Linux under both user mode and kernel mode. All programs use memory for its execution in some form or the other. These normally depends upon underlying operating system for its memory usage i.e., memory supply is an OS service to user programs.

Linux, like most of the OS have two modes of operation; one mode is called as user mode in which most of the applications and user processes runs for most of the time. Another mode is called as kernel mode. Most of the OS and system software runs in this mode; most of the user programs have small portion of code (e.g. system calls and privilege instructions) which runs in kernel mode. How memory needs is fulfilled in both these execution contexts are different and thus be seen from different perspective.


1. Memory issues in user mode

Most of the user level memory allocation is done by system calls or the program reserves space statically at compile time. Every program is assigned some memory in form of stack and heap for allocating space to variables and other data objects. System calls which are mostly used for dynamic allocation of memory are malloc(), calloc(), realloc(),brk() etc. These either allocate requested memory or returns a null pointer. A good thing about user mode memory allocation is that error checking at time of memory checking could be avoided for the obvious reason that it would have as a worst effect, kill the program. Further upon memory corruption or segmentation fault, the programmer can mask the signal and do minimal housekeeping activities before program crashes out. Memory allocation and deallocation are simple at this level and programmer don't have to worry about outcomes of call.


2. Memory issues in kernel mode

Memory allocation is very delicate and needs to be done carefully in kernel mode because a slight error can corrupt the whole system map and crash the system. In kernel mode, memory is allocated dynamically by two ways (in true sense).

kmalloc()

The kmalloc() function allocates memory at two levels: it uses a "bucket" system to allocate memory in units up to nearly a page (4Kb on the i86) in length, and uses a "buddy" system on lists of different sizes of contiguous chunks of memory to allocate memory in units up to 128Kb (on the i86) in length (buddy algo given in book by knuth). However recently, it is able to allocate memory in excess of basic page size of system but the chances of getting a bigger chunk is much lesser then for lower sizes. kmalloc() system call is widely used for dynamic memory allocation. Its syntax is described below :

void * kmalloc(unsigned int size, int priority);

where size refers to the actual size of the block requested and priority determines relative urgency or decides which cache table (one for DMA/ISA and other for KERNEL) will be used for allocation. Further it follows best fit algorithm wherein, it searches for the smallest size where requested memory fits in. kmalloc() allocates memory from the kernel and upon allocation, it doesn't clear the contents of memory blocks. kmalloc() is specially used in all types of LKM, particularly in TCP IP protocol stack where it is used to allocate memory to protocol buffers (sk_buff). Memory allocated with kmalloc() is freed with kfree().

get_free_pages()

This is the lowest-level of dynamically allocating memory and used in cases where memory is needed in range of a quarter of a page or half the page. In such cases memory allocated by kmalloc results in much greater internal fragmentation. Its syntax is given below :

void* get_free_page(int priority);

This API is usually used by vmalloc() to allocate variable length pages. get_free_page(priority) will allocate a single page memory based upon one of the GFP_* values (passed as priority). However here the contents of the page are not cleared and thus program shouldn�t try to interpret its content. In order to allocate more than one page, you can call get_free_pages(priority, order) where priority is same as before and, the order argument gives the size according to the following formula:

size=PAGE_SIZE*(2^order)

However, this formula could yield pages in binary power. Pages allocated with get_free_page() are freed with free page().

Error handling issues

As a general rule, the programmer must explicitly check for errors just after memory allocation as well as after every update, because here you cannot mask errors nor redirect them. Best way to minimize such happening is that use of centralized buffer manager. Here u request kernel to allocate a big chunk of memory prior to execution of main part and there after let your own program distribute the memory as and how it likes. This way requests to kernel for memory allocation will be minimized and this will lessen the chances of failure. Off course, the programmer, needs to maintain the details of the memory chunk which it distributes among various sub modules. Another trivial technique could be to allocate memory just as u enter a function, so that in case some fault occurs, you can safely exit. Memory is one of the scarcest and most commonly needed of the resources that must be guaranteed, and the only way to guarantee that memory will be available is to allocate it prior to execution.


I am Nikhil Bhargava from Delhi, India. I am a Computer Engineer with research intrests in mobile networks and operating systems. Comments and Suggestions are always welcome.
Hosted by www.Geocities.ws

1