systemtap targets
Target变量
- 默认变量
变量一般是在一个probe内的
local
变量 - 全局变量
如果需要在probe之间共享变量,则需要在声明时加上
global
- target变量
target变量是用来获取被探测事件代码内部结构的变量,可以使用
-L
选项来查看某个探测点可以使用的target变量:stap -L 'kernel.function("vfs_read")'
kernel.function("vfs_read@fs/read_write.c:294") $file:struct file* $buf:char* $count:size_t $pos:loff_t*
再看下fs/read_write.c
的vfs_read
函数,这些target变量其实就是vfs_read
函数的传参:ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
- 举例说明target变量的用法
比如监控进程读取文件时,打印出被读取文件的inode
从上面stap -L 'kernel.function("vfs_read")'
知道vfs_read
有struct file*
类型的file
target变量
查看内核源码结构体struct file*
(定义在include/linux/fs.h
)
再查看结构体struct path
(定义在include/linux/path.h
)
再查看结构体struct dentry
(定义在include/linux/dcache.h
)
终于找到了inode(定义在include/linux/fs.h
)
最后,我们得到了这样一个变量:$file->f_path->dentry->d_inode->i_ino
编写systemtap脚本如下:
probe kernel.function("vfs_read").return
{
if(execname() != "stapio")
printf("%s[%ld], %ld\n", execname(), pid(), $file->f_path->dentry->d_inode->i_ino)
}
vmstat[5117], 4026532032
使用find / -inum 4026532032
可以看到4026532032
这个inode对应的是/proc/meminfo
文件
如何打印出文件名呢,再看下第4
步中的dentry
结构体,其中有struct qstr d_name;
,再查看struct qstr
(定义在include/linux/dcache.h
)
文件名就是这个name
变量了:$file->f_path->dentry->d_name->name
但是有个问题,从struct qstr
的定义上我们可以得知,$file->f_path->dentry->d_name->name
变量是个指针,也就是个地址(长整型),如何可以获取该指针指向的内容,也就是我们需要的文件名呢?
systemtap内置带有获取内核空间数据的函数,这一系列函数的作用就是读取内核内存中address
所指向的不同类型的数据:
kernel_char(address)
kernel_short(address)
kernel_int(address)
kernel_long(address)
kernel_string(address)
kernel_string_n(address, n)
由此我们可以用kernel_string($file->f_path->dentry->d_name->name)
来获取文件名,将脚本改写如下:
probe kernel.function("vfs_read").return
{
if(execname() != "stapio")
printf("%s[%ld], %ld, %s\n", execname(), pid(), $file->f_path->dentry->d_inode->i_ino, kernel_string($file->f_path->dentry->d_name->name))
}
probe timer.s(2)
{
exit()
}
vmstat[16556], 4026532032, meminfo