hello-list.c

Apr 25, 2010 15:46


C programming language is not very popular nowadays.  I don't care. I like the language.
It was very interesting to learn how linked lists are implemented in the Linux kernel.  This picture illustrates them nicely:


A custom structure - the type of objects you want to enlist - contains `struct list_head' as its member. This is not a pointer (that's the point) and you can place it anywhere (!) within the structure (i.e., it doesn't have to be the first member).
You use list_head members for list operations (insertion, deletion, iteration, etc.; all the nice stuff defined in linux/list.h).  And when you need the rest of your data structure - you use `list_entry' macro. `list_entry' fetches a pointer to the container object from its `struct list_head' member.
This is my "hello world" program (skip down to `struct Char' and `main' function):

#include #include #include /* * List operations are copied from ; * see <http://lxr.linux.no/#linux+v2.6.33/include/linux/list.h>. * * See also <http://www.xml.com/ldd/chapter/book/ch10.html#t5>, * there is a nice picture. */ struct list_head { struct list_head *next, *prev; }; #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) static inline void INIT_LIST_HEAD(struct list_head *list) { list->next = list; list->prev = list; } static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; } /** * list_add_tail - add a new entry * @new: new entry to be added * @head: list head to add it before * * Insert a new entry before the specified head. * This is useful for implementing queues. */ static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } /** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. * * NOTE: This definition differs from the one in . */ #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr) - offsetof(type, member))) /** * __list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. * @head: the head for your list. * * This variant differs from list_for_each() in that it's the * simplest possible list iteration code, no prefetching is done. * Use this for code that knows the list to be very short (empty * or 1 entry) most of the time. */ #define __list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) /* ------------------------------------------------------------------ */ /* Custom data type. */ struct Char { char value; struct list_head _; }; static struct Char * new_Char(char c) { struct Char *x = malloc(sizeof(struct Char)); INIT_LIST_HEAD(&x->_); x->value = c; return x; } int main(void) { LIST_HEAD(xs); { /* Populate a list with allocated Chars */ const char *p; for (p = "Hello, world!"; *p != 0; ++p) list_add_tail(&new_Char(*p)->_, &xs); } { /* Print */ const struct list_head *p; __list_for_each(p, &xs) putchar(list_entry(p, struct Char, _)->value); putchar('\n'); } { /* Free allocated memory */ const struct list_head *p = xs.next; while (p != &xs) { void *x = list_entry(p, struct Char, _); p = p->next; free(x); } INIT_LIST_HEAD(&xs); } return 0; }
See also:

code, english, c, linux

Previous post Next post
Up