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) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
struct list_head *p;
struct ipstore *store;
list_for_each(p, &addr_list)
{
store = list_entry(p, struct ipstore, list);
if(store->addr[0] == ist->addr[0])
{
if(ist)
kfree(ist);
break;
}
}
INIT_LIST_HEAD(&ist->list);
list_add(&ist->list, &addr_list);
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))
32/3<123>