原文出处z2007b http://blog.csdn.net/z2007b/article/details/6370383。
linux内核的双向链表是比较经典的东西,网上分析链表的同志基本分析了99%,就差了1%。那就是list_del函数。
先给出函数原型:entry->next = NULL;
entry->prev = NULL;
我们先看一下相关的注释:/** * list_del - deletes entry from list. * @entry: the element to delete from the list. * Note: list_empty on entry does not return true after this, the entry is * in an undefined state. */ void list_del(struct list_head *entry) { WARN(entry->next == LIST_POISON1, "list_del corruption, next is LIST_POISON1 (%p)\n", LIST_POISON1); WARN(entry->next != LIST_POISON1 && entry->prev == LIST_POISON2, "list_del corruption, prev is LIST_POISON2 (%p)\n", LIST_POISON2); WARN(entry->prev->next != entry, "list_del corruption. prev->next should be %p, " "but was %p\n", entry, entry->prev->next); WARN(entry->next->prev != entry, "list_del corruption. next->prev should be %p, " "but was %p\n", entry, entry->next->prev); __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; }这个地方有对这两个宏的引用。这个函数的警告信息告诉我们这个节点已经被用过了,很显然,我们将其与平常意义的节点作比较可以得到如下信息:我们得到的这个链表是被删掉的,不是刚初始化没用的。另外我大胆猜测了一下其另一个用途:就算我们不打开CONFIG_DEBUG_LIST这个宏,我们在调试出错代码的时候经常会返回指针的值,我们很多时候出错都是指针为NULL造成的,这时候我们如果发现是值是LIST_POISON1或LIST_POISON2的话,那我们马上可以将注意力转移到链表上来了,并且是因为误用了一个已经从链表中删除掉的节点。