/* list_entry */ /** * 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_head within the struct. */ #define list_entry(ptr, type, member) \ container_of(ptr, type, member)
/** * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * */ #define container_of(ptr, type, member) ({ \ void *__mptr = (void *)(ptr); \ ((type *)(__mptr - offsetof(type, member))); })
/** * @ptr: the list head to take the element from. * @type: the type of the struct this is embedded in. * @member: the name of the list_head within the struct. */ // 实际就是使用container_of通过list_head地址来获取原结构体的地址 #define list_entry(ptr, type, member) \ container_of(ptr, type, member)
/** * Delete a list entry by making the prev/next entries * point to each other. * * This is only for internal list manipulation where we know * the prev/next entries already! */ staticinlinevoid __list_del(struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; }
// include/linux/poison.h /* * These are non-NULL pointers that will result in page faults * under normal circumstances, used to verify that nobody uses * non-initialized list entries. */ #define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) #define LIST_POISON2 ((void *) 0x122 + POISON_POINTER_DELTA)
/** * list_del - deletes entry from list. * @entry: the element to delete from the list. * Note: list_empty() on entry dose not return true after this, the entry * is in an undefined state. */ // 删除entry这个节点,并让其prev、next指向一个错误地址 staticinlinevoidlist_del(struct list_head *entry) { __list_del_entry(entry); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; }
遍历list_head
通过list_head的头节点向后遍历整个链表
1 2 3 4 5 6
/** * @pos: the &struct list_head to use as a loop cursor * @head: the head for your list */ #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next)
/** * @pos: the &struct list_head to use as a loop cursor * @n: another &struct list_head to use a temporary storage * @head: the head for your list */ #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != head; \ pos = n, n = pos->next)
通过list_head的头节点向前遍历链表
1 2 3
#define list_for_each_prev_safe(pos, n, head) \ for (pos = (head)->prev, n = pos->prev; pos != head; \ pos = n, n = pos->prev)
/** * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry * @pos: the type * to use as a loop cursor. * @n: another type * to use as temporary storage * @head: the head for your list. * @member: the name of the list_head within the struct. */ #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_first_entry(head, typeof(*pos), member), \ n = list_next_entry(pos, member); \ !list_entry_is_head(pos, head, member); \ pos = n, n = list_next_entry(n, member))
/** * early_platform_cleanup - clean up early platform code */ void __init early_platform_cleanup(void) { structplatform_device *pd, *pd2;
/* clean up the devres list used to chain devices */ list_for_each_entry_safe(pd, pd2, &early_platform_device_list, dev.devres_head) { list_del(&pd->dev.devres_head); memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head)); } }
spin_lock(&k->k_lock); // 将klist_node的n_klist标记为dead if (kill) knode_kill(n); if (!klist_dev_and_del(n)) put = NULL; spin_unlock(&k->k_lock); if (put) put(n); }