CSE 422S: Studio 12

Kernel Memory Management


"This is not to say that, from a programmer's point of view, kernel memory allocations are difficult -- just different."

—Robert Love, Linux Kernel Development, 3rd Ed., Chapter 12, pp. 231

The Linux kernel offers several approaches to memory management, including a variety of memory allocation and deallocation facilities for use in kernel space, which offer different trade-offs between memory utilization and performance. In today's studio you will explore three of them: page-level management, (physically contiguous) object-level management, and slab allocation.

In this studio, you will:

  1. Allocate and deallocate memory for different numbers of objects, using three different kernel memory management approaches; and
  2. measure the latency for doing that with each approach.

Please complete the required exercises below.

As you work through these exercises, please record your answers, and when finished email your results to eng-cse422s@email.wustl.edu with the phrase Kernel Memory Management in the subject line.

Make sure that the name of each person who worked on these exercises is listed in the first answer, and make sure you number each of your responses so it is easy to match your responses with each exercise.


Required Exercises

  1. As the answer to the first exercise, list the names of the people who worked together on this studio.

  2. Write code for a kernel module that takes a single unsigned integer parameter, which defaults to 2,000 if no value is provided for it. The module's initialization function should create a single kernel thread that is pinned to one core (which one to use is at your discretion) and that simply outputs a message to the system log (i.e., using printk) that contains the value of the module parameter (which will be the number of objects for which memory will be allocated and then deallocated).

    Compile your module, and load it on your Raspberry Pi and check that the message appears in the system log. Then unload your module and as the answer to this exercise please show the code that implements your module.

  3. In a terminal window on your Raspberry Pi, run the command

    getconf PAGE_SIZE

    which will give the size of a kernel memory page, in bytes.

    Inside your module, declare a struct type that contains an array of 8 unsigned integers. In your module's thread function, print a second message to the system log that says how large that struct is (in bytes). You can use sizeof and the struct type to do this.

    As the answer to this exercise, say (1) how large each kernel memory page is, (2) how large the struct type you declared is, and (3) how many instances of that struct type would fit within a single kernel memory page.

  4. Inside the module's thread function, after the initial messages are sent to the system log, use an appropriate clock to obtain the current time, and store that value in a local variable.

    Immediately after that, use the alloc_pages function to allocate enough memory pages to contain the number of structs given in the module parameter - i.e., the smallest power of 2 that would be sufficient based on your calculation of the number of objects per page in the previous exercise.

    Immediately after that, use the free_pages function to deallocate those pages.

    Immediately after that, use the same clock as before to obtain the current time, and print a message to the system log with how much time all the memory allocation and deallocation took.

    Compile and then load and unload your module on your Raspberry Pi, with values 1,000 and then 2,000 and then 4,000 and as the answer to this exercise please say how much time was spent on memory allocation and deallocation for each of those cases.

  5. Make a copy of your kernel module code, in a new file. In that file, replace the page-level memory allocation and deallocation approach with a loop that runs as many times as the value given in the module paramenter, and in each iteration of the loop (1) uses kmalloc to allocate just enough memory for an instance of the struct type and then (2) immediately uses kfree to deallocate that memory.

    Compile and then load and unload your new module on your Raspberry Pi, with values 1,000 and then 2,000 and then 4,000 and as the answer to this exercise please say how much time was spent on memory allocation and deallocation for each of those cases.

  6. Copy that version of your kernel module into a new file, and change the memory allocation and deallocation scheme to use slab allocation. Specifically, your new module's init function should use kmem_cache_create to create a new cache for the module's struct type, and store a pointer to it in a global variable, and your new module's exit function should use kmem_cache_destroy to destroy the cache. Then inside the loop within the thread function of your new module, replace the calls to kmalloc and kfree with appropriate calls to kmem_cache_alloc and kmem_cache_free respectively, instead.

    Compile and then load and unload your new module on your Raspberry Pi, with values 1,000 and then 2,000 and then 4,000 and as the answer to this exercise please say how much time was spent on memory allocation and deallocation for each of those cases.

  7. Compare and contrast the results you saw for each of the module parameter values, and for each of the memory allocation and deallocation approaches. As the answer to this exercise, please describe briefly any trends you saw as the number of objects to allocate memory for increased, and/or as the memory allocation approach changed.

Things to turn in