crash基本使用
- 在crash中通过 [想要查看的参数] [参数地址] 可以看到当前的数据
如 css_set 0xffff8f4871aad840
或 css_set.cg_links 0xffff8f4871aad840 - list -H [表头地址] 遍历链表
- struct -o [数据地址] 查看指定数据的数据结构
crash> list help
NAME
list - linked list.
.
SYNOPSIS
list [[-o] offset][-e end][-[s|S] struct[.member[,member] [-l offset]] -[x|d]]
[-r|-B] [-h|-H] start
crash获取进程的task
# 获取设备的task_struct
# 1. task [pid]
crash> task 1987
PID: 1987 TASK: ffff8f47fb3f4200 CPU: 1 COMMAND: "sleep"
struct task_struct {
state = 1,
... ...
# 2. 先获取地址,再task [address]
crash> ps | grep sleep
1987 1862 1 ffff8f47fb3f4200 IN 0.0 108052 620 sleep
crash> task ffff8f47fb3f4200
PID: 1987 TASK: ffff8f47fb3f4200 CPU: 1 COMMAND: "sleep"
struct task_struct {
state = 1,
stack = 0xffff8f47e9a28000,
... ...
获取task对应的cgroup
linux中没有数据结构直接描述task所属的cgroup,而是通过css来包含了这层关系。因为实际运行时,获取task所属cgroup的操作请求出现频率比较小,而请求子系统状态的操作会非常频繁。参考文档
可以通过两条路径获取到
task->css_set->css-> cgroup
# 创建一个测试进程
[root@aliyun-xxx ~]# sleep 36000 &
[1] 6997
[root@aliyun-xxx ~]# sleep 36000 & # 默认cgroup,用于对比
[2] 2893
# task-> css_set
# 查看进程对应的css_set
crash> task -R cgroups 6997
PID: 6997 TASK: ffff8f47f5166300 CPU: 1 COMMAND: "sleep"
cgroups = 0xffff8f47e5a20cc0,
# task -> css_set -> css
# 对比默认cgroup的css,可以发现pids:/test对应的css地址为 0xffff8f47e9f93720
crash> css_set.subsys 0xffff8f47e5a20cc0
subsys = {0xffffffff9c464520, 0xffffffff9c90abc0, 0xffffffff9c45d220, 0xffff8f487b14d400, 0xffff8f487b169a80, 0xffff8f487b13a8a0, 0xffff8f487b13a900, 0xffffffff9c4d6820, 0xffff8f487b13a960, 0xffff8f487b139d80, 0xffff8f47e9f93720, 0xffff8f487b10d300}
# 默认cgroup进程的css
crash> css_set.subsys 0xffff8f47aac45900
subsys = {0xffffffff9c464520, 0xffffffff9c90abc0, 0xffffffff9c45d220, 0xffff8f487b14d400, 0xffff8f487b169a80, 0xffff8f487b13a8a0, 0xffff8f487b13a900, 0xffffffff9c4d6820, 0xffff8f487b13a960, 0xffff8f487b139d80, 0xffff8f487b13a9c0, 0xffff8f487b10d300}
# task -> css_set -> css -> cgroup
# 以pids为例,获取到task的cgroup pids:/test
crash> cgroup_subsys_state 0xffff8f47e9f93720
struct cgroup_subsys_state {
cgroup = 0xffff8f4776836800, # get !!
refcnt = {
counter = 1
},
flags = 2,
id = 0x0,
dput_work = {
data = {
counter = 68719476704
},
entry = {
next = 0xffff8f47e9f93748,
prev = 0xffff8f47e9f93748
},
func = 0xffffffff9b928c70
}
}
task-> css_set-> cg_cgroup_link -> cgroup
# 创建一个测试进程
[root@aliyun-xxx ~]# sleep 36000 &
[1] 6997
# task-> css_set
# 查看进程对应的css_set
crash> task -R cgroups 6997
PID: 6997 TASK: ffff8f47f5166300 CPU: 1 COMMAND: "sleep"
cgroups = 0xffff8f47e5a20cc0,
# 查看task对应的css_set的cg_links(指向关联的cg_cgroup_link)
# task-> css_set-> cg_cgroup_link
crash> css_set.cg_links 0xffff8f47e5a20cc0
cg_links = {
next = 0xffff8f478cc40518,
prev = 0xffff8f478cc404d8
}
# 注意,这里取到的不是cg_cgroup_link的地址,是cg_cgroup_link.cg_link_list
crash> struct -o css_set.cg_links 0xffff8f47e5a20cc0
struct css_set {
[ffff8f47e5a20ce8] struct list_head cg_links;
}
# 可以看到进程关联了12个cg_cgroup_link
crash> list -H ffff8f47e5a20ce8 | wc -l
12
# task-> css_set-> cg_cgroup_link -> cgroup
# 获取到cgroup = 0xffffffff9c464520
crash> list -l cg_cgroup_link.cg_link_list -s cg_cgroup_link.cgrp -H ffff8f47e5a20ce8
ffff8f478cc40518
cgrp = 0xffffffff9c93d030
ffff8f478cc40858
cgrp = 0xffff8f4786b98c00
ffff8f478cc40a58
cgrp = 0xffff8f48753f2030
ffff8f478cc40158
cgrp = 0xffff8f487b226030
ffff8f478cc40c58
cgrp = 0xffff8f487b222030
ffff8f478cc402d8
cgrp = 0xffff8f487b220030
ffff8f478cc400d8
cgrp = 0xffff8f487b224030
ffff8f478cc40d18
cgrp = 0xffff8f4872406030
ffff8f478cc40498
cgrp = 0xffff8f4872404030
ffff8f478cc40258
cgrp = 0xffff8f4872402030
ffff8f478cc40318
cgrp = 0xffff8f4776836800 # get!!
ffff8f478cc404d8
cgrp = 0xffff8f487246c030
获取cgroup对应的task
前面知道, 由task到cgroup有两条路径。但是,虽然可以通过cgroup查看到关联的css,但是由于css与cgroup是多对多关系,并且css和task也是多对多的关系,所以通过css没办法直接获取到cgroup对应的task。所以内核引入了cg_cgroup_link来关联。
具体路径为:cgroup -> cg_cgroup_link -> css_set -> task
由上文获取到的cgroup[0xffff8f4776836800]
为例,获取task
# 查看与cgroup关联的css数组*subsys[]
# 可以看到只关联了一个css,即对应一个子系统
crash> cgroup.subsys 0xffff8f4776836800
subsys = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff8f47e9f93720, 0x0}
# 要获取task,需要通过一个中间结构cg_cgroup_link (此处参考3.10.x版本,5.x版本这部分结构有变动)
# cgroup -> cg_cgroup_link
# cgroup.css_sets指向cgroup对应的所有cg_cgroup_link链表,可以看到这个cgroup对应的链表只有一个节点
crash> cgroup.css_sets 0xffff8f4776836800
css_sets = {
next = 0xffff8f478cc40300,
prev = 0xffff8f478cc40300
}
crash> struct -o cgroup.css_sets 0xffff8f4776836800
struct cgroup {
[ffff8f47768368c0] struct list_head css_sets;
}
# cgroup -> cg_cgroup_link -> css_set
crash> list -l cg_cgroup_link.cgrp_link_list -s cg_cgroup_link -H ffff8f47768368c0
ffff8f478cc40300
struct cg_cgroup_link {
cgrp_link_list = { # 指向cgroup.css_sets(即包含该cg_cgroup_link的链表)用于直接遍历该cgroup的所有cg_cgroup_link(得到css_sets)
next = 0xffff8f47768368c0,
prev = 0xffff8f47768368c0
},
cgrp = 0xffff8f4776836800, # 指向cg_cgroup_link关联的cgroup
cg_link_list = { # 指向css_set.cg_links,用于遍历该css_set关联的所有cg_cgroup_link(得到所有cgroup)
next = 0xffff8f478cc404d8,
prev = 0xffff8f478cc40258
},
cg = 0xffff8f47e5a20cc0 # 指向cg_cgroup_link关联的css_set
}
# cgroup -> cg_cgroup_link -> css_set [-> css_set.tasks]
crash> css_set.tasks 0xffff8f47e5a20cc0
tasks = {
next = 0xffff8f47f5166c48,
prev = 0xffff8f47f5166c48
}
# cgroup -> cg_cgroup_link -> css_set [-> css_set.tasks -> task_struct.cg_list]
crash> list -H 0xffff8f47f5166c48
ffff8f47e5a20cd8
# cgroup -> cg_cgroup_link -> css_set -> task
crash> list -l task_struct.cg_list -s task_struct.pid -H ffff8f47e5a20cd8
ffff8f47f5166c48
pid = 6997
获取css_set对应的task_struct
两者的关系如下图
task_struct和css_set 通过cg_list和tasks互相关联
crash> task -R cg_list 6997
PID: 6997 TASK: ffff8f47f5166300 CPU: 1 COMMAND: "sleep"
cg_list = {
next = 0xffff8f47e5a20cd8,
prev = 0xffff8f47e5a20cd8
},
crash> list -H 0xffff8f47e5a20cd8
ffff8f47f5166c48
crash> task -R cgroups 6997
PID: 6997 TASK: ffff8f47f5166300 CPU: 1 COMMAND: "sleep"
cgroups = 0xffff8f47e5a20cc0,
crash> css_set.tasks 0xffff8f47e5a20cc0
tasks = {
next = 0xffff8f47f5166c48,
prev = 0xffff8f47f5166c48
}
crash> list -H 0xffff8f47f5166c48
ffff8f47e5a20cd8
# 通过计算偏移量获取css_set.cg_list对应的task_struct地址
crash> list -l task_struct.cg_list -s task_struct -H ffff8f47e5a20cd8
ffff8f47f5166c48
struct task_struct {
state = 1,
stack = 0xffff8f48767c0000,
usage = {
counter = 2
... ...
# 获取到css_set对应的task
crash> list -l task_struct.cg_list -s task_struct.group_leader -H ffff8f47e5a20cd8
ffff8f47f5166c48
group_leader = 0xffff8f47f5166300
【参考】
[结构关系图]https://blog.csdn.net/hu1610552336/article/details/118642410
[crash实例] http://linux.laoqinren.net/kernel/cgroup-source-css_set-and-cgroup/#css_set%E5%92%8Ccgroup%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB