Linked Lists


The Linux kernel's implementation of a linked list is contained in a header file called list.h. (The version linked is modified slightly to remove dependencies on other kernel headers so that the file can be used in userspace.) You can download the file to your projects' source directory, and include it in a C source file as:


      #include "list.h"
      

Design

The general idea with list.h is that we create lists where all elements are the same type of struct, and we embed the list within the struct.

Let's say we have a struct person:


      struct person {
          char *name;
          int age;
      };
      

To chain this struct in a list, we embed list.h's struct list_head:


      struct person {
          struct list_head list;
          char *name;
          int age;
      };
      

If we examine list.h, we will see that struct list_head is defined as


      struct list_head {
        struct list_head *prev, *next;
      };
      

In other words, it represents a node in a doubly-linked list. For the head of the list we simply use a bare struct list_head: one that is not embedded in a struct person.

The linked list implementation relies on a few clever macros to go from a "pointer to the embedded struct list" to a "pointer to the struct that contains it" (the struct person). These macros are used internally within list.h: it is extremely rare that you will use them directly, but it is interesting to see how they work:


      #ifndef offsetof
      #define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)
      #endif

      #define container_of(ptr, type, member)                            \
        ({                                                         \
          const typeof(((type *)0)->member) *__mptr = (ptr); \
          (type *)((char *)__mptr - offsetof(type, member)); \
        })
      

The header file list.h defines a lot of functions; the most common ones are:

LIST_HEAD(name)
Declare a list head variable called name
INIT_LIST_HEAD(name)
Initialize a list head
list_add(new, head)
Add entry to front of list (entry will be just after head)
list_add_tail(new, head)
Add entry to back of list
list_del(entry)
Delete entry from list
list_empty(head)
Tests whether a list is empty
list_first_entry(ptr, type, member)
Get the first element from the list (the list is expected not to be empty)
list_last_entry(ptr, type, member)
Get the last element from the list (the list is expected not to be empty)
list_for_each_entry(pos, head, member)
Iterate over a list of a given type
list_for_each_entry_safe(pos, n, head, member)
Iterate over list of given type safe against removal of list entry

Examples

Basic Usage

The following program shows the basic usage of a list.



      

Implementing a Stack

The following program implements a stack:



      

Implementing a Queue

The following program implements a queue: