3、在链表中增加一个节点
static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); } |
要调用此函数,只要在上一步后面接上:
list_add(&ist->list, &addr_list); |
完整的增加操作:
struct ipstore *ist; ist = kmalloc(sizeof (*ist), GFP_ATOMIC); if(!ist) { printk("kmalloc failed.\n"); return -1; } ist->time = jiffies+time*HZ; ist->addr[0] = 0xc0a80101;//IP:192.168.1.1 INIT_LIST_HEAD(&ist->list); list_add(&ist->list, &addr_list); |
这样在链表addr_list中就增加了新的链表节点。
4、遍历链表
为什么不先讲删除节点,因为很多情况下都是先遍历链表,找到匹配的节点后再去删除的,所以先讲遍历链表,遍历链表分普通遍历和安全删除遍历,可见如果要删除链表结点我们就需要使用安全删除遍历。
普通遍历,主要使用在当加入节点时判断是否有相同的结点存在,如果已存在就不需要再往下操作了,如下判断是否有相同的IP地址存在。
#define list_for_each(pos, head) \ struct list_head *p; |
ist就是上一步的链表结点指针,如果链表中有IP和新增节点IP地址相同的节点则释放刚分配的新节点空间,不进行任何操作,否则加入addr_list链表中。
内核提供了一个比较简单的接口,可以在遍历的同时取出节点,此函数内部封装了list_entry():
#define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ prefetch(pos->member.next), &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) |