最近学习Linux内核代码,两句指针代码顿时让我感觉自己的指针功底还是欠缺。在此对代码重新做了梳理、分析及记录。
源代码结构也挺简单。如下:
static struct rtable *rt_base = NULL;
static void rt_del(unsigned long dst, char *devname)
{
struct rtable *r, **rp;
rp = &rt_base;
// ………… 省略部分代码
while((r = *rp) != NULL)
{
/* Make sure both the destination and the device match */
if ( r->rt_dst != dst ||
(devname != NULL && strcmp((r->rt_dev)->name,devname) != 0) )
{
rp = &r->rt_next;
continue;
}
*rp = r->rt_next;
// ………… 省略部分代码
kfree_s(r, sizeof(struct rtable));
}
}
在程序初始化时 rt_base 是一个指向路由链表头的指针;上述代码中有两行相似且不容易理解的代码:1、rp = &r->rt_next; 2、*rp = r->rt_next; 以下做以分析。
首先将上述指针的结构及指向如下图:

上图画出了代码中涉及三个变量:struct rtable *rt_base;struct rtable *r, **rp 的结构在起初第一次刚进while循环时的指针所指位置(图中所有的地址都是自己假设的;假设链表节点内容长度为0x10,可以算出第一个节点的next指针的地址为:0x1011)。
假设第一次进入while循环且if条件成立,此时 r = *rp 执行后:此时 r (值为:0x1001)指向 rt_base 链表的表头 ,&r->rt_next 为 0x1011; 此时函数会执行 rp = &r->rt_next;此时 rp 存储中的值由0x2020(rt_base 指针的地址)变为 0x1011(链表第一个节点的next指针的地址)。此时的 *rp (值为:0x1041)指向链表的第二个节点,continue 继续跳回while执行。
假设第二次进入while循环且if条件不成立,此时 r = *rp 执行后:r (值为:0x1041)指向链表的第二个节点;r->rt_next 为链表的第三个节点;rp(值为:0x1011)存放的是第一个节点的next指针的地址;此时执行 *rp = r->rt_next;即为:将第一个节点的next指针指向第三个节点。
所以总结为:该函数是删除不满足 if 条件的节点。
本文详细分析了Linux内核代码中关于删除路由链表节点的实现。通过示例代码,解释了指针操作`rp=&r->rt_next`和`*rp=r->rt_next`的功能,指出它们如何更新链表结构,从而实现删除不匹配条件的节点。文章适合有一定C语言和Linux内核基础的读者深入理解指针和链表操作。
200

被折叠的 条评论
为什么被折叠?



