Linux内核链表学习笔记

复习数据结构的时候,顺便找来经典的Linux内核链表来强化下。

由于Linux内核链表没有采用经典的“指针+数据域”的结构进行组织,而是由链表只负责管理前驱指针和后继指针,而由存储实际数据的数据结构来负责数据的组织。所以要采用这种链表,数据结构中必须有list_head这个数据域。

 

这个数据结构的特点是,把类型信息与链表结构独立开来。不像C++是采用模板,那么需要对template< class T >中的每种T都重载某些函数和操作符,这个链表是把这些类型信息都独立到使用该链表的数据中去,链表只是作为一个载体。

 

访问通过这些list_head连接起来的链表时,是巧妙地利用了内存对struct分配的空间关系。因为一个struct的内容是在内存中连续分配的,所以可以用指针直接移动一定的字节来移动到数据的场所。

我自己写了一个DATA的数据结构。在这个结构中struct list_head list是处于内存的低地址空间,int val是出于相对的高地址空间。而且sizeof(struct list_head) = 8就是两个指针的大小,所以可以把上个链表节点指向当前节点的链表指针加8就可以移动到val的地址。

 

比如

 

 

需要注意的是,temp的赋值过程。因为dat2.list.next的类型是——struct list_head*,大小为8个字节,所以后面sizeof(struct list_head)= 8,那么实际上移动了8×8=64个字节,而不是预料中的8个字节。因为指针的加减也要依据数据类型。所以要达到加8个字节的效果,必须先把指针转换为int指针。

 

最后应该成功输出1。

 

这是我对linux内核链表的最初的一点体会,还很不成熟,以后慢慢研究。

 

P.S. 在这个过程中,顺便学习了gdb的调试的一些简单操作,以前是只会break, list, print, run,今天继续学习info, backtrace

 

 

(gdb) info f

Stack level 0, frame at 0x22ff30:

 eip = 0x4013e9 in main (list.c:21); saved eip 0x4010db

 source language c.

 Arglist at 0x22ff28, args:

 Locals at 0x22ff28, Previous frame's sp is 0x22ff30

 Saved registers:

  ebp at 0x22ff28, eip at 0x22ff2c

(gdb) p &dat1.list

$1 = (struct list_head *) 0x22ff10

(gdb) p &dat1.val

$2 = (int *) 0x22ff18

(gdb) p dat2.list.next

$3 = (struct list_head *) 0x22ff10

(gdb) p sizeof(list_head)

No symbol "list_head" in current context.

(gdb) p sizeof(struct list_head)

$4 = 8

(gdb) p *(int*)(dat2.list.next + 8)

$5 = 1991710238

(gdb) p (int*)(dat2.list.next + 8)

$6 = (int *) 0x22ff50

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值