单链表 使用 while(p) 进行判断

这种模式比while(p->next)更常见,用于完整遍历链表,每个节点处理一次。buffer_head和sk_buff frag_list是典型单链表例子。

1,buffer_head单链表遍历(b_this_page作为next),找到尾部并闭环。用于页面缓冲管理,确保链表完整。

在内核 fs/buffer.c 文件中,980行:

buffer_head单链表遍历(b_this_page作为next),找到尾部并闭环。用于页面缓冲管理,确保链表完整。

static void buffer_check_tail(struct folio *folio, size_t size)
{
    struct buffer_head *head = folio_buffers(folio);
    struct buffer_head *tail;
    struct buffer_head *bh = head;
    do 
    {        
    			tail = bh;
    			bh = bh->b_this_page;
    } while (bh);  
    // while (bh != NULL)
    	
    	tail->b_this_page = head;
}

2, fs/buffer.c 284行的__find_get_block_slow函数

遍历页面中的buffer_head链表,检查uptodate状态,直到NULL。
用于块设备读操作。

<br>static int __find_get_block_slow(struct inode *inode, sector_t block)
{
    tmp = bh;
    do {
    	if (!buffer_uptodate(tmp))
    		folio_uptodate = 0;
    		...
    		tmp = tmp->b_this_page;
    	} while (tmp != bh);  
    	// 结合while (tmp != NULL) 检查
    }

3, net/core/skbuff.c 1718行 的 skb_queue_purge 函数

sk_buff队列(next指针单链表)遍历,释放所有节点。
用于网络包清理,等价while (p != NULL)。

static void skb_queue_purge(struct sk_buff_head *list)
{
	struct sk_buff *skb;
	while ((skb = __skb_dequeue(list)) != NULL)
	    kfree_skb(skb);
	}

4, net/ipv6/reassembly.c 300行的 frag6_reasm 函数

IPv6分片sk_buff单链表(next指针)遍历,重组包。用于网络栈。

static struct sk_buff *frag6_reasm(
									struct frag_queue *fq, \
									struct net_device *dev, \
									const struct ipv6hdr *hdr, \
									int *offset)
{
	struct sk_buff *head = fq->fragments;
	struct sk_buff *next;
	while (head != NULL) 
	{  
		// while (head != NULL)
		next = head->next;
		...        
		head = next;<br>    
	}
}

说明

  • 单链表确认:这些例子中,b_this_pagesiblingnext都是单向指针,形成单链表。
  • 内核中单链表常用于性能敏感场景,如缓冲区链或包片段。
  • 为什么变量不是p:内核代码使用描述性变量(如bh for buffer_head、tmp for temporary)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值