参考:
https://crash-utility.github.io/help_pages/list.html
笔记:
头节点是A_head:
struct A_head { // -h
... // -O
struct list_head list; // -H
int b; // -s
};
普通节点是A:
struct A { // -h
... // -o
struct list_head list; // -H
char pid; // -s
};
假设将来A通过A.node挂到A_head.
-H: list的地址
-h: A_head或者A的地址
-o: 在普通节点中list在A中的偏移,格式A.list
-O: 在头结点中list在A中的偏移,格式A_head.list。当头节点跟普通节点不同的时候需要这个参数,在输出的内容里不会输出头节点的内容。
-s: 要查看的结构体的成员
示例
- 遍历线程组thread_group
当创建线程的时候,当前进程下的所有线程的task_struct
都通过thread_node
挂在了task_struct->signal->thread_head
下面。
list_add_tail_rcu(&p->thread_group,
&p->group_leader->thread_group);
list_add_tail_rcu(&p->thread_node,
&p->signal->thread_head);
线程组中的task的signal是相同的,所以先获取signal的地址,然后遍历thread_head链表即可。
以task 714为例:
crash> task -R signal 714
PID: 714 TASK: ffff889e1449c000 CPU: 14 COMMAND: "kvm"
signal = 0xffff889ecdaab600,
然后查看thread_head的地址:
crash> signal_struct.nr_threads,thread_head 0xffff889ecdaab600
nr_threads = 17
thread_head = {
next = 0xffff889ecd9789b8,
prev = 0xffff88a031cf89b8
}
当前线程组有17个线程,开始遍历:
crash> list -o task_struct.thread_node -s task_struct.pid,tgid -H ffff889ecdaab610
ffff889ecd978000
pid = 451
tgid = 451
ffff889ed1c44000
pid = 452
tgid = 451
ffff8899f8bb2000
pid = 456
tgid = 451
ffff8897bc884000
pid = 480
tgid = 451
ffff8897bc880000
pid = 487
tgid = 451
ffff8897bc882000
pid = 488
tgid = 451
ffff8897bc886000
...
-
遍历cgroup_root
-
以下面的数据结构关系为例:
说明:
- head_node使用head_list连接到list_head_test中
- head_node之间有父子关系
- head_node的node通过node.list连到head_node.node_list下面
- 所有的node通过node.slib连接在一起
- 查看
list_head_test
地址
crash> sym list_head_test
ffffffffad245b30 (d) list_head_test
- 查看
list_head_test
链表下挂的head_node
crash> list -o head_node.head_list -s head_node.name -H ffffffffad245b30
ffff93b2850c3b40 // struct head_node的地址
name = 0xfffffffface7a68f "head1",
ffff93b2850c3b80 // struct head_node的地址
name = 0xfffffffface7a695 "head2",
ffff93b2850c3bc0 // struct head_node的地址
name = 0xfffffffface7a69b "head3",
- 查看
head1
的parent
crash> list -o head_node.parent -s head_node.name ffff93b2850c3b40
ffff93b2850c3b40
name = 0xfffffffface7a68f "head1",
ffff93b2850c3b80
name = 0xfffffffface7a695 "head2",
ffff93b2850c3bc0
name = 0xfffffffface7a69b "head3",
在结构体中,parent
没有采用list_head
链表,所以不能用-h
或者-H
- 查看
head_node1
下的node
成员
crash> list -o node.list -s node.name -O head_node.node_list -h ffff93b2850c3b40
ffff93b2850c3c00
name = 0xfffffffface7a6a1 "node1",
ffff93b2850c3c40
name = 0xfffffffface7a6a7 "node2",
ffff93b2850c3c80
name = 0xfffffffface7a6ad "node3",
- 查看
head_node2
下的node
成员
crash> list -o node.list -s node.name -O head_node.node_list -h ffff93b2850c3b80
ffff93b2850c3cc0
name = 0xfffffffface7a6b3 "node4",
ffff93b2850c3d00
name = 0xfffffffface7a6b9 "node5",
ffff93b2850c3d40
name = 0xfffffffface7a6bf "node6",
- 查看
head_node3
下的node
成员
crash> list -o node.list -s node.name -O head_node.node_list -h ffff93b2850c3bc0
ffff93b2850c3d80
name = 0xfffffffface7a6c5 "node7",
ffff93b2850c3dc0
name = 0xfffffffface7a6cb "node8",
ffff93b2850c3e00
name = 0xfffffffface7a6d1 "node9",
- 查看
node.slib
链表中的成员
使用node1的起始地址
crash> list -o node.slib -s node.name -h ffff93b2850c3c00
ffff93b2850c3c00
name = 0xfffffffface7a6a1 "node1",
ffff93b2850c3c40
name = 0xfffffffface7a6a7 "node2",
ffff93b2850c3c80
name = 0xfffffffface7a6ad "node3",
ffff93b2850c3cc0
name = 0xfffffffface7a6b3 "node4",
ffff93b2850c3d00
name = 0xfffffffface7a6b9 "node5",
ffff93b2850c3d40
name = 0xfffffffface7a6bf "node6",
ffff93b2850c3d80
name = 0xfffffffface7a6c5 "node7",
ffff93b2850c3dc0
name = 0xfffffffface7a6cb "node8",
ffff93b2850c3e00
name = 0xfffffffface7a6d1 "node9",
如果使用-O参数,那么会把传入地址当作头节点,输出的内容不包含头节点的内容:
crash> list -o node.slib -s node.name -O node.slib -h ffff93b2850c3c00
ffff93b2850c3c40
name = 0xfffffffface7a6a7 "node2",
ffff93b2850c3c80
name = 0xfffffffface7a6ad "node3",
ffff93b2850c3cc0
name = 0xfffffffface7a6b3 "node4",
ffff93b2850c3d00
name = 0xfffffffface7a6b9 "node5",
ffff93b2850c3d40
name = 0xfffffffface7a6bf "node6",
ffff93b2850c3d80
name = 0xfffffffface7a6c5 "node7",
ffff93b2850c3dc0
name = 0xfffffffface7a6cb "node8",
ffff93b2850c3e00
name = 0xfffffffface7a6d1 "node9",