linux 3.10的list_del
最近看到一个page的数据比较奇怪:
crash> page ffffea002c239c58
struct page {
flags = ,
_count = {
counter = 34-----------------------被引用34次
},
{
_mapcount = {
counter = -1---------------------没有映射
},
{
inuse = ,
objects =
}
},
{
{
private = ,
mapping = 0x0------------------为NULL,
},
ptl = {
raw_lock = {
slock =
}
},
slab = 0x0,
first_page = 0x0
},
{
index = ,------------index这么大,明显不对
freelist = 0xffff881508fda880------------转成16进制,这个倒是像对的
},
lru = {
next = 0xdead000000100100,
prev = 0xdead000000200200
}
}
查看一下这个地址:
crash> kmem 0xffff881508fda880
CACHE NAME OBJSIZE ALLOCATED TOTAL SLABS SSIZE
ffff880c17fb0d00 mm_struct 8k
SLAB MEMORY TOTAL ALLOCATED FREE
ffff881508fda280 ffff881508fda300
FREE / [ALLOCATED]
ffff881508fda880 PAGE PHYSICAL MAPPING INDEX CNT FLAGS
ffffea00499f77b0 1508fda000 c0000000000080 slab
最后看到的是lru的next和prev成员,一开始才疏学浅,觉得这个 0xdead000000100100 和 0xdead000000200200 很奇怪。
后来搜索之后,才发现这个是将一个entry删除之后,设置的标记值:
/*
* Architectures might want to move the poison pointer offset
* into some well-recognized area such as 0xdead000000000000,
* that is also not mappable by user-space exploits:
*/
#ifdef CONFIG_ILLEGAL_POINTER_VALUE
# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
#else
# define POISON_POINTER_DELTA
#endif /*
* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
*/
#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)
#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
删除的代码实现如下:
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
不光光是list,hlist也有类似动作:
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
在用户态程序中,我们一般通过判断指针是不是是null来判断能否使用这个指针,在将一个entry从list删除后,一般将prev和next设置为NULL,这样做没有什么问题,但是这样就没有
区分这个entry是从list摘除的,还是本身初始化的,所以为了调试方便,将其设置为一些特殊值,是有意义的。
当开启调试之后,即开启 CONFIG_DEBUG_LIST,则在加入链表和删除的时候都会加入调试warn
void __list_del_entry(struct list_head *entry)
{
struct list_head *prev, *next; prev = entry->prev;
next = entry->next; if (WARN(next == LIST_POISON1,
"list_del corruption, %p->next is LIST_POISON1 (%p)\n",
entry, LIST_POISON1) ||
WARN(prev == LIST_POISON2,
"list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
entry, LIST_POISON2) ||
WARN(prev->next != entry,
"list_del corruption. prev->next should be %p, "
"but was %p\n", entry, prev->next) ||
WARN(next->prev != entry,
"list_del corruption. next->prev should be %p, "
"but was %p\n", entry, next->prev))
return; __list_del(prev, next);
}
void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
WARN(next->prev != prev,
"list_add corruption. next->prev should be "
"prev (%p), but was %p. (next=%p).\n",
prev, next->prev, next);
WARN(prev->next != next,
"list_add corruption. prev->next should be "
"next (%p), but was %p. (prev=%p).\n",
next, prev->next, prev);
WARN(new == prev || new == next,
"list_add double add: new=%p, prev=%p, next=%p.\n",
new, prev, next);
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
当然,如果你摘链之后,还要继续挂链的话,还是要初始化的,这个时候就使用:
static inline void
list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);-----------------------会重新初始化
}
linux 3.10的list_del的更多相关文章
- linux 学习10 shell 基础
10.1 Shell概述 .Shell是什么 Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动.挂起.停止甚至是编写一 ...
- Linux系统性能10条命令监控
Linux系统性能10条命令监控 概述 通过执行以下命令,可以在1分钟内对系统资源使用情况有个大致的了解. uptime dmesg | tail vmstat 1 mpstat -P ALL 1 p ...
- 使用john破解ubuntu(linux)9.10密码
Title:使用john破解ubuntu(linux)9.10密码 --2011-11-23 15:00 ubuntu 9.10的账户密码加密方式改用sha512了,默认的john是破不了的,还好官方 ...
- Linux系统管理10——进程和计划任务管理
Linux系统管理10——进程和计划任务管理 一.程序和进程的关系 1.程序 ·保存在硬盘.光盘等介质中的可执行代码和数据 ·静态保存的代码 2.进程 ·在CPU及内存中运行的程序代码 ·动态执行的代 ...
- Linux系统启动那些事—基于Linux 3.10内核【转】
转自:https://blog.csdn.net/shichaog/article/details/40218763 Linux系统启动那些事—基于Linux 3.10内核 csdn 我的空间的下载地 ...
- Linux 4.10.8 根文件系统制作(一)---环境搭建
一.工具 制作工具为busybox 下载地址:https://busybox.net/ 解压: 二.制作文件系统 进入目录,执行make menuconfig: 2.1 busybox setting ...
- 交叉编译和安装ARM板(RK3288)和Linux 3.10上的RTL8188无线网卡驱动
插入无线网卡,输入ifconfig,发现没有检测到网卡. 输入lsusb,查看无线网卡型号. 我用的无线网卡是EDUP的网卡,包装盒里有一张驱动光盘,把光盘里linux下的驱动目录复制下来.如果没有驱 ...
- Linux 4.10中两个新特性与我的一段故事
今早5点半起来没有開始写文章,而是去西湾红树林连跑带走折腾了将近20公里.回来后就8点多了...洗了个澡之后坐稳当.開始写一段关于我的故事. 在2014年到2015年期间,我在负责研发一 ...
- [转] Linux 3.10 ARM Device Tree 的初始化
[转] Linux 3.10 ARM Device Tree 的初始化 本文代码均来自标准 linux kernel 3.10,可以到这里下载 https://www.kernel.org/ ...
随机推荐
- TF-IDF算法原理
原文:https://www.cnblogs.com/biyeymyhjob/archive/2012/07/17/2595249.html TF-IDF(term frequency–inverse ...
- delphi版本对应
delphi 7 delphi 8delphi 2005 ----- 9delphi 2006 ----- 10 delphi 2007 ----- 11delphi 2009 ----- 12 de ...
- 用VirtualBox快速安装虚拟机virtual Machine(Win7+IE10)
前端测试,经常需要各种环境, 用“Virtual Box + OVA文件”安装虚拟机, 是简单高效的一种方法,可以安装各种window和IE的版本.下面以IE10 + Win7为例说明. 1) 下载和 ...
- 安装MySQL半同步复制
一.简介 从MySQL5.5开始,MySQL以插件的形式支持半同步复制.如何理解半同步呢?首先我们来看看异步,全同步的概念 异步复制(Asynchronous replication) MySQL默认 ...
- CentOS7中替换安装python3.7.0
python3.7的安装包可从官网下载上传到主机,也可以用wget直接下载. [root@xxx ~]# cd /usr/local/src/[root@xxx src]# wget https:// ...
- jQuery对象的属性操作
jquery的属性操作模块分为四个部分:html属性操作,dom属性操作,类样式操作和值操作 html属性操作:是对html文档中的属性进行读取,设置和移除操作.比如attr().removeAttr ...
- python中logging模块的一些简单用法
用Python写代码的时候,在想看的地方写个print xx 就能在控制台上显示打印信息,这样子就能知道它是什么了,但是当我需要看大量的地方或者在一个文件中查看的时候,这时候print就不大方便了,所 ...
- Junit Rdeis No tests found matching 单机版安装
redis安装(SecureCRT工具上传redis 3.0.0) 1.mkdir redis 创建文件夹2.tar –zxvf redis-3.0.0.tar.gz –C /redis/ 解压到re ...
- tkinter events format
tkinter label 标签主要显示,通常不与用户进行交互事件 frame容器上获取点击的事件坐标 event.x,event.y event.key获取键盘数据
- yarn 日志查看
1. yarn 日志列表 yarn application -list 2. impala-shell impala-shell -q 'invalidate metadata' ## impala ...