在Linux内核中,printk函数可以打印相关信息,并在/var/log/syslog中查看到对应的输出。但是,当需要在内核中统计一些信息的时候,由于数据较多,此刻,在syslog中会发生大量的信息丢失,因而,我们需要在内核中使用文件来存储统计信息。

由于需要在内存模块中使用文件,这就引发了一个问题:文件系统可能还未加载到内核中,在内存模块中无法使用文件。解决方法:在内存管理模块中,应该不断循环判断,直到文件系统加载到内核中,此刻,就可以使用文件来存储统计信息。

虚拟机实验中ksm(页面访问频率统计)是具体使用的例子,在这里只解析使用文件的代码片段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#define MY_FILE "/home/test/stat.txt" //定义存放统计信息的文件
struct file *log_file = NULL; //定义对应的file结构体
char str_buf[64]; //暂存数据缓冲区

static void write_to_file(void *buffer, size_t length)
{
if (IS_ERR(log_file)){
return;
}
mm_segment_t old_fs;
old_fs = get_fs();
set_fs(KERNEL_DS);
vfs_write(log_file, (char *)buffer, length, &log_file->f_pos);
set_fs(old_fs);
}

处理逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
while (true) {
if (log_file == NULL){
log_file = filp_open(MY_FILE, O_RDWR | O_APPEND | O_CREAT, 0777);
}
if (IS_ERR(log_file)){
log_file = filp_open(MY_FILE, O_RDWR | O_APPEND | O_CREAT, 0777);
}
if(log_file != NULL && !IS_ERR(log_file)){
sprintf(str_buf, "22222222:%ul:%d\n", page_to_pfn(page), tem); //sprintf与printf用法相同
write_to_file((void *)str_buf, strlen(str_buf));
}
}

这样,就可以在内存模块使用文件了。