博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
内核链表使用--删除链表节点
阅读量:5266 次
发布时间:2019-06-14

本文共 2709 字,大约阅读时间需要 9 分钟。

分类: 2011-04-06 14:28 434人阅读 (0) 收藏

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

当我们使用遍历的方法来删除链表时:

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

 

转载于:https://www.cnblogs.com/pengdonglin137/p/3583886.html

你可能感兴趣的文章
打飞机游戏【来源于Crossin的编程教室 http://chuansong.me/account/crossincode 】
查看>>
[LeetCode] Merge Intervals
查看>>
【翻译自mos文章】当点击完 finishbutton后,dbca 或者dbua hang住
查看>>
Linux编程简介——gcc
查看>>
2019年春季学期第四周作业
查看>>
MVC4.0 利用IActionFilter实现简单的后台操作日志功能
查看>>
windows下mongodb安装与使用
查看>>
rotate the clock
查看>>
bugku 变量
查看>>
Python 环境傻瓜式搭建 :Anaconda概述
查看>>
数据库01 /Mysql初识以及基本命令操作
查看>>
数据库02 /MySQL基础数据类型以及多表之间建立联系
查看>>
Python并发编程04/多线程
查看>>
CF461B Appleman and Tree
查看>>
CF219D Choosing Capital for Treeland
查看>>
杂七杂八的小笔记本
查看>>
51Nod1353 树
查看>>
CF1215E Marbles
查看>>
fish redux 个人理解
查看>>
BZOJ2339 HNOI2011卡农(动态规划+组合数学)
查看>>