`
womendu
  • 浏览: 1481760 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

内核链表使用--删除链表节点

 
阅读更多

内核链表使用--删除链表节点

当我们使用遍历的方法来删除链表时:
list_for_each(pos, &student_list)
{
list_del(pos);
}

list_for_each(pos, head)这个宏定义是用来遍历链表的,通过其第一个参数pos来删除链表节点,但是,运行后就会出现以下错误:

Unable to handle kernel paging request at virtual address 00100100
pgd = c3aa8000
[00100100] *pgd=33a82031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1]
last sysfs file: /sys/devices/virtual/vc/vcsa4/dev
Modules linked in: mylist(-) [last unloaded: mylist]
CPU: 0 Not tainted (2.6.32.2 #1)
PC is at cleanup_module+0x48/0x64 [mylist]
LR is at sys_delete_module+0x1e8/0x25c
pc : [<bf012048>] lr : [<c00603cc>] psr: 00000013
sp : c3a99f40 ip : bf0122e0 fp : 00000000
r10: be825e88 r9 : c3a98000 r8 : c002e024
r7 : c3a99f44 r6 : 00000880 r5 : bf01219c r4 : 00000000
r3 : bf0122e4 r2 : bf0122e4 r1 : 00100100 r0 : c3a480d8
Flags: nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: c000717f Table: 33aa8000 DAC: 00000015
Process rmmod (pid: 849, stack limit = 0xc3a98270)
Stack: (0xc3a99f40 to 0xc3a9a000)
9f40: c3ab8c80 696c796d 00007473 00000000 00000000 c35d8828 00000062 c0091bf8
9f60: 00000000 00000000 00000000 c3ab8c80 00000000 c3a9a6c0 c3ab8c80 00000000
9f80: bf01219c 00000880 c3a99f8c 00000000 c3ab8c80 be825f63 00000001 00000000
9fa0: 00000081 c002dea0 be825f63 00000001 be825f63 00000880 4022a024 00000001
9fc0: be825f63 00000001 00000000 00000081 00000001 00000000 be825e88 00000000
9fe0: 00000000 be825b10 00018250 401c886c 60000010 be825f63 00000000 00000000
[<bf012048>] (cleanup_module+0x48/0x64 [mylist]) from [<c00603cc>] (sys_delete_module+0x1e8/0x25c)
[<c00603cc>] (sys_delete_module+0x1e8/0x25c) from [<c002dea0>] (ret_fast_syscall+0x0/0x28)
Code: e59fc018 e1a0300c e4931004 e1510003 (e5910000)
---[ end trace 2e1cdf07b6db8d2d ]---
Segmentation fault

原因在于使用list_for_each(pos, head)来遍历整个链表时,依赖于pos->next,从他的代码实现就可以看出来:
/*include/linux/list.h*/
#define list_for_each(pos, head) /
for (pos = (head)->next; prefetch(pos->next), pos != (head); /
pos = pos->next)
而删除节点函数
list_del(pos);
会把pos的后向链表post->next指向另外一个地址,见函数原型:
/*include/linux/list.h*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
/*include/linux/Poison.h*/
#define LIST_POISON1 ((void *) 0x00100100)
而这个地址正好是出错信息提示的地址0x00100100。

正确的做法其实应该使用另外一个遍历宏定义:
/*include/linux/list.h*/
#define list_for_each_safe(pos, n, head) /
for (pos = (head)->next, n = pos->next; pos != (head); /
pos = n, n = pos->next)
这里用n做了pos的备份,当处理完for循环里的事情后,又把n的值重新赋回给pos,确保pos结构里的值不被改变。

JJDeng@SCUT
jjdeng.scut@gmail.com
2011.01.19

该贴来源于http://blog.ednchina.com/supertramp/1977039/Message.aspx

分享到:
评论

相关推荐

    基于Linux的内核链表源代码

    1、内核链表的节点创建、删除、遍历等 2、内核链表的使用实践 (1)问题:内核链表只有纯链表,没有数据区域,怎么使用? 使用方法是将内核链表作为将来整个数据结构的结构体的一个成员内嵌进去。类似于公司收购...

    linux内核链表介绍与了解

    链表是一种常用的组织有序数据的数据结构,它通过指针将一系列数据节点连接成一条数据链,是线性表的一种重要实现方式。相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以...

    C语言的双链表

    内核链表是一种双向循环链表,内核链表的节点节点结构中只有指针域 使用内核链表的时候,将内核链表作为一个成员放入到一个结构体中使用 我们在链表中找到内核链表结构的地址,通过这个地址就可以找到外部大结构体...

    Linux中的内核链表实例详解

    链表中一般都要进行初始化、插入、删除、显示、释放链表,寻找节点这几个操作,下面我对这几个操作进行简单的介绍,因为我的能力不足,可能有些东西理解的不够深入,造成一定的错误,请各位博友指出。 A、Linux内核...

    深入分析 Linux操作系统的内核链表

    链表是一种常用的组织有序数据的数据结构,它通过指针将一系列数据节点连接成一条数 据链,是线性表的一种重要实现方式。相对于数组,链表具有更好的动态性,建立链表时...本文将为大家分析 Linux操作系统的内核链表。

    C语言的单链表

    内核链表是一种双向循环链表,内核链表的节点节点结构中只有指针域 使用内核链表的时候,将内核链表作为一个成员放入到一个结构体中使用 我们在链表中找到内核链表结构的地址,通过这个地址就可以找到外部大结构体...

    双向链表list.c

    为《仿照linux内核的链表构造并...文件里面有链表声明和初始化、判断链表是否为空、表头插入、表尾插入、遍历、反向遍历、由链表节点到数据项、删除节点的详细注解和示例。 在linux下用gcc list.c编译,./a.out运行。

    疯狂内核之——进程管理子系统

    3.3 调度程序所使用的函数 151 3.3.1 scheduler_tick函数 151 3.3.2 try_to_wake_up函数 156 3.3.3 recalc_task_prio函数 160 3.4 schedule()函数 163 3.4.1 直接调用 163 3.4.2 延迟调用 164 3.4.3 进程切换之前所...

    UNIX 高级教程系统技术内幕

    10.6.2 删除打开文件 l0.6.3 读和写 10.7 NFS 性能 10.7.1 性能瓶颈 10.7.2 客户端高速缓存 10.7.3 延迟写 10.7.4 重传高速缓存 10.8 专用NFS 服务器 10.8.1 Auspex 功能性多处理器结构 10.8.2 IBM 的HA-NFS 服务器 ...

Global site tag (gtag.js) - Google Analytics