概述
前言
bpf提供了一种方法,可以使用户在内核函数运行的某个阶段(如运行前和运行后)插入一段用户指定的程序并运行。这篇文章实现了一个bpf小程序,可以查看某个文件是否全部被缓存到page cache中,并打印出文件被缓存了多少页和文件一共有多少页
1. 安装bcc
以centos
发行版为例,直接yum install bcc -y
即可
其他系统请参见INSTALL
2. bpf程序源码
#!/usr/bin/env python3
#coding=utf-8
from __future__ import print_function
from bcc import BPF
from bcc.utils import printb
import sys
import argparse
# arguments
examples = """examples:
./stacksnoop # print nr_cached_pages and nr_all_pages for all files that called sys_read
./stacksnoop -f ext4_sync_fs # print nr_cached_pages and nr_all_pages for 'ext4_sync_fs' file
./stacksnoop -p 185 -f ext4_sync_fs # ... only when PID 185 is on-CPU
"""
parser = argparse.ArgumentParser(
description="Trace and print kernel stack traces for a kernel function",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=examples)
parser.add_argument("-p", "--pid",
help="trace this PID only")
parser.add_argument("-f", "--f_name",
help = "trace this file only")
args = parser.parse_args()
# define BPF program
bpf_text = """
#include <uapi/linux/ptrace.h>
#include <linux/pagemap.h>
static int my_strlen(const char* str) {
int i = 0;
for(; str[i] != '\0'; ++i) { }
return i;
}
void trace_start(struct pt_regs *ctx, struct file *file, char __user *buf, size_t count, loff_t *ppos) {
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
unsigned long nr_cached_pages = 0;
unsigned long nr_all_pages = 0;
loff_t size = 0;
const unsigned char *f_name = file->f_path.dentry->d_name.name;
const char *filter_name = "NAME";
int i = 0;
u32 pid = bpf_get_current_pid_tgid();
PID_FILTER
NAME_FILTER
nr_cached_pages = mapping->nrpages;
bpf_probe_read(&size, sizeof(inode->i_size), &inode->i_size);
size += (PAGE_CACHE_SIZE - 1);
nr_all_pages = (size -1) >> PAGE_CACHE_SHIFT;
bpf_trace_printk("file_name:%s nr_cached_pages:%lu nr_all_pages:%lu\n", f_name, nr_cached_pages, nr_all_pages);
}
"""
if args.pid:
bpf_text = bpf_text.replace('PID_FILTER',
'if (pid != %s) { return; }' % args.pid)
else:
bpf_text = bpf_text.replace('PID_FILTER','')
if args.f_name:
bpf_text = bpf_text.replace('NAME_FILTER',
'for(; i < my_strlen(filter_name); ++i) { if (filter_name[i] != f_name[i]) return ;}')
bpf_text = bpf_text.replace('NAME', args.f_name)
else:
bpf_text = bpf_text.replace('NAME_FILTER','')
# print(bpf_text)
# init BPF
b = BPF(text=bpf_text)
if BPF.get_kprobe_functions(b'vfs_read'):
print("trace vfs_read succ")
b.attach_kprobe(event="vfs_read", fn_name="trace_start")
else:
print("don't support trace vfs_read, exit")
sys.exit(-1)
# print header
print("%-16s %-6s %s" % ("COMM", "PID", "MESSAGE"))
# format output
while 1:
try:
(task, pid, cpu, flags, ts, msg) = b.trace_fields()
printb(b"%-16s %-6d %s" % (task, pid, msg))
except KeyboardInterrupt:
exit()
3. 使用方法
第一列打印进程名,第二列打印进程pid,第三列打印我们自定义消息
nr_cached_pages
是已经被page cache所缓存的页面数量,nr_all_pages
是文件所有的页面数量
可以看到,第一次读his
文件时,并没有文件内容被缓存,第二次则全部被page cache所缓存
注意,使用时最好使用-f
或者-p
参数,否则会把所有正在读文件的进程全部打印出来
最后
以上就是虚拟橘子为你收集整理的【linux kernel 3.10】查看文件内容是否全部被page cache所缓存的全部内容,希望文章能够帮你解决【linux kernel 3.10】查看文件内容是否全部被page cache所缓存所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复