168static inline void list_del(struct list_head *entry)
169{
170 __list_del(entry->prev, entry->next);
171 entry->next = LIST_POISON1;
172 entry->prev = LIST_POISON2;
173}
list_del是删除entry所在的链表的entry节点,在171和172行将
entry->next=LIST_POISON1;
entry->prev=LIST_POISON2;
而LIST_POISON1和LIST_POISON2都被定义在:/linux/include/linux/poison.h中:
10#define LIST_POISON1 ((void *) 0x00100100)
11#define LIST_POISON2 ((void *) 0x00200200)
我的问题是:
1、一般我们在操作双向链表时,删除一个节点的操作是将该节点从链表中删除,之后
要么直接释放该节点,要么将其返回,而此处没有释放也 没有返回,而是赋予了
LIST_POISON1 和LIST_POISON12这两个值,是何用意?
2、这两个位置是什么内容?有什么特殊?将entry->next和entry->prev分别指向这两个
位置,那可不可以指向其他无效的位置?
3、这两个位置是人为规定的?并且对于所有访问它的程序都给予确定的回应(就像访问
0x00000000就会出现断错误这样的回应)?
--
My Bolg: http://niutao.cublog.cn
在linux内核中,/linux/include/linux/list.h
21struct list_head {
22 struct list_head *next, *prev;
23};
list_head被用做建立双向循环链表,其中对它的一个操作是删除一个节点:
155static inline void __list_del(struct list_head * prev, struct
list_head * next)
156{
157 next->prev = prev;
158 prev->next = next;
159}
168static inline void list_del(struct list_head *entry)
169{
170 __list_del(entry->prev, entry->next);
171 entry->next = LIST_POISON1;
172 entry->prev = LIST_POISON2;
173}
list_del是删除entry所在的链表的entry节点,在171和172行将
entry->next=LIST_POISON1;
entry->prev=LIST_POISON2;
而LIST_POISON1和LIST_POISON2都被定义在:/linux/include/linux/poison.h中:
10#define LIST_POISON1 ((void *) 0x00100100)
11#define LIST_POISON2 ((void *) 0x00200200)
我的问题是:
1、一般我们在操作双向链表时,删除一个节点的操作是将该节点从链表中删除,之后
要么直接释放该节点,要么将其返回,而此处没有释放也 没有返回,而是赋予了
LIST_POISON1 和LIST_POISON12这两个值,是何用意?
2、这两个位置是什么内容?有什么特殊?将entry->next和entry->prev分别指向这两个
位置,那可不可以指向其他无效的位置?
3、这两个位置是人为规定的?并且对于所有访问它的程序都给予确定的回应(就像访问
0x00000000就会出现断错误这样的回应)?
--
My Bolg: http://niutao.cublog.cn
/*
* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
*/
--
The opposite of love is not hate, but indifference.
--Elie Wiesel
内核的虚拟内存是从PAGE_OFFSET开始的,所以那两个地址显然不在这个
范围内。所以会产生段错误吧。
显然。上面不就是个好例子么?
>
>
你不需要source insight那种工具,你只要grep就足够了。
而且,你也知道,遇到函数指针时cscope是无法跟踪的,这时你只能用grep。
(source insight是window$的工具,我从来不用,不过我猜它也很难跟踪到)
> 作处理的函数..
> 690 net/rxrpc/af_rxrpc.c <<rxrpc_release_sock>>
> ASSERTCMP(rx->listen_link.next, !=, LIST_POISON1);
很明显这是在net/rxrpc下。照你这样说,如果每个使用list的都这么处理的话,
那么这种宏应该在一个高层的目录中,比如最理想的include/linux,而不会出现
在net/rxrpc这种底层的子目录中。
> 这是一种:
> #define ASSERTCMP(X, OP, Y) \
> do { \
> if (unlikely(!((X) OP (Y)))) { \
> printk(KERN_ERR "\n"); \
> printk(KERN_ERR "RxRPC: Assertion failed\n"); \
> printk(KERN_ERR "%lu " #OP " %lu is false\n", \
> (unsigned long)(X), (unsigned long)(Y)); \
> printk(KERN_ERR "0x%lx " #OP " 0x%lx is false\n", \
> (unsigned long)(X), (unsigned long)(Y)); \
> BUG(); \
> } \
> } while(0)
> 另外一种:
> #define ASSERTCMP(X, OP, Y) \
> do { \
> } while(0)
Are you sure?
你注意到#ifdef 1了么?
P.S.
如果你的逻辑正确,我至少应该能在kernel/,arch/x86,mm/等地方找到这种宏,
很不幸,我grep不到。
<snip>
>> 关于这个地址的处理内核处理的很简单,要么打印日志信息报错,要么直接不处理. 我的linux下的source
>> insight不能用了,这是我用cacope查出来的一个对此种地址 作处理的函数..
>> 690 net/rxrpc/af_rxrpc.c <<rxrpc_release_sock>>
>> ASSERTCMP(rx->listen_link.next, !=, LIST_POISON1);
>> 这是一种:
>> #define ASSERTCMP(X, OP, Y) \
>> do { \
>> if (unlikely(!((X) OP (Y)))) { \
>> printk(KERN_ERR "\n"); \
>> printk(KERN_ERR "RxRPC: Assertion failed\n"); \
>> printk(KERN_ERR "%lu " #OP " %lu is false\n", \
>> (unsigned long)(X), (unsigned long)(Y)); \
>> printk(KERN_ERR "0x%lx " #OP " 0x%lx is false\n", \
>> (unsigned long)(X), (unsigned long)(Y)); \
>> BUG(); \
>> } \
>> } while(0)
>> 另外一种:
>> #define ASSERTCMP(X, OP, Y) \
>> do { \
>> } while(0)
>>
>这才是我想要的答案,谢谢学长。
为什么这么容易盲从别人呢??你稍微grep一下LIST_POISION1你就会发现:
./include/linux/poison.h:10:#define LIST_POISON1 ((void *) 0x00100100)
./include/linux/list.h:110: entry->next = LIST_POISON1;
./include/linux/list.h:514: n->next = LIST_POISON1;
./Documentation/scsi/ChangeLog.lpfc:516: removed (100100 is a
LIST_POISON1 value from the next pointer
./lib/list_debug.c:75: entry->next = LIST_POISON1;
./net/rxrpc/af_rxrpc.c:690: ASSERTCMP(rx->listen_link.next, !=,
LIST_POISON1);
如果他说的是对的,怎么可能只有net/rxrpc中那样使用??应该有很多使用
list地方都用到才对!所以那只是个例。
记住,不要轻易相信别人的观点,包括我的!
690 net/rxrpc/af_rxrpc.c <<rxrpc_release_sock>>
ASSERTCMP(rx->listen_link.next, !=, LIST_POISON1);
宏的定义文件:
1 813 fs/afs/internal.h <<ASSERTCMP>>
#define ASSERTCMP(X, OP, Y) \
2 869 fs/afs/internal.h <<ASSERTCMP>>
#define ASSERTCMP(X, OP, Y) \
3 695 net/rxrpc/ar-internal.h <<ASSERTCMP>>
#define ASSERTCMP(X, OP, Y) \
4 736 net/rxrpc/ar-internal.h <<ASSERTCMP>>
#define ASSERTCMP(X, OP, Y) \
在内核中确实我现在还没有找到其它有关这个LIST_POISON处理的函数.
>
如果访问了POSITION1会出现什么情况?
这里不是已经回答了么?
/*
* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
*/
>
>
>
>> >>
>>
>>
>
>
>
#ifdef 1告诉我,它永远都会打印信息。。。。
> 我是在以下文件中找到这中宏的.至于这个宏在LIST_POISON上的应用我
> 只在这一个文件中找到:
>
> 690 net/rxrpc/af_rxrpc.c <<rxrpc_release_sock>>
> ASSERTCMP(rx->listen_link.next, !=, LIST_POISON1);
我们这的话题是LIST_POISON,很明显我只在乎它,ASSERTCMP是什么是次要。
既然你只在一个net/rxrpc/文件中找到,那就是个例,并不是处理LIST_POISON
的通用方法,因此你的解释不恰当。
Over.