list_add_tail 双向链表实现分析 .

http://blog.csdn.net/panda19881/article/details/7654698

 

在看内核v4l2示例代码driver/media/video/vivi.c时 ,看到list_add_tail()函数,现在对其进行分析:


  1. struct list_head {  
  2.     struct list_head *next, *prev;  
  3. };  
  4.   
  5.  list_add_tail(&buf->vb.queue, &vid->active);  
  6. /** 
  7.  * list_add_tail - add a new entry 
  8.  * @new: new entry to be added 
  9.  * @head: list head to add it before 
  10.  * 
  11.  * Insert a new entry before the specified head. 
  12.  * This is useful for implementing queues. 
  13.  */  
  14. static __inline__ void list_add_tail(struct list_head *_new, struct list_head *head)  
  15. {  
  16.     __list_add(_new, head->prev, head);  
  17. }  
  18.   
  19. /* 
  20.  * Insert a new entry between two known consecutive entries. 
  21.  * 
  22.  * This is only for internal list manipulation where we know 
  23.  * the prev/next entries already! 
  24.  */  
  25. static __inline__ void __list_add(struct list_head * _new,  
  26.                   struct list_head * prev,  
  27.                   struct list_head * next)  
  28. {  
  29.     next->prev = _new;  
  30.     _new->next = next;  
  31.     _new->prev = prev;  
  32.     prev->next = _new;  
  33. }  
struct list_head {
    struct list_head *next, *prev;
};

 list_add_tail(&buf->vb.queue, &vid->active);
/**
 * 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);
}

/*
 * Insert a new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
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;
}

很多地方说:这个函数完成的功能就是添加一个新的结点在head的左边,其实不然,它是从右向左在head->priv和head两个节点之间插入_new。


假设刚开始建立链表,只有struct list_head *head,

那么前两句话有用:将next->prev = _new;
                            _new->next = next;

这就是将new节点添加到head 节点的左边,那么接 下来两句没用:   _new->prev = prev;  prev->next = _new;

如果head左边已近有了其他节点,那么调用list_add_tail()函数后,前边两句的功能一样,都是把新的节点添加在head左边,而后两句就是把新节点添加在原来head之前节点(head->priv)右边,这样就串起来了。


那list_add就反过来,把新的节点添加在head和head之后的节点(head->next)之间;


关于list_add和list_add_tail建立栈和FIFO:

list_add和list_add_tail都是在head两边插入新的节点,所以list_add先插入的节点向右移,head->next是最后插入的节点,list_add_tail先插入的节点向左移,head->next是最先插入的节点;

遍历链表都是从head开始向下,所以用list_add建立的链表先访问的是最后插入的节点,类似于栈;list_add_tail建立的链表先访问的是最先插入的节地点,类似于FIFO。


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值