如何使用proc文件打印mem_map的信息?



我现在正在尝试打印mem_map的虚拟地址,mem_map的物理地址和结构页的数量。 所以我尝试运行本文的代码,但似乎没有显示正确的地址。 你能告诉我如何解决这个问题吗?

下面是执行的结果。

mem_map virt addr: (null( mem_map 物理地址:131941395333120 mem_map物理页数:18446744072101367984

我使用的是 Ubuntu12.04(64 位(,内核版本是 3.13。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/switch_to.h>
#include <linux/types.h> /* size_t */
#include <linux/fcntl.h> /* O_ACCMODE */
#include <asm/uaccess.h> /* copy_from/to_user */
#include <linux/fs.h>       // for basic filesystem
#include <linux/proc_fs.h>  // for the proc filesystem
#include <linux/seq_file.h> // for sequence files
#include <linux/mm.h>
MODULE_LICENSE("Dual BSD/GPL");
static struct proc_dir_entry* proc_file;
struct page *mem_map;
EXPORT_SYMBOL(mem_map);
/* memory map functions */
int mem_map_show(struct seq_file *m, void *v);
//virtual_to_physical
inline unsigned long virt_to_phy(unsigned long addr);
inline unsigned long virt_to_phy(unsigned long addr){
return __pa(addr);
}
char buf[300];
int mem_map_show(struct seq_file *m, void *v){
int ret_val = 0;
printk(KERN_INFO "Proc file read n");
ret_val =  seq_printf(m, "mem_map virt addr: %p n", mem_map);
ret_val += seq_printf(m, "mem_map phys addr: %lu n",virt_to_phy((unsigned long)mem_map));
ret_val += seq_printf(m, "mem_map phys pages: %lu n", (long unsigned int)get_num_physpages);
return ret_val;
}
static int mem_map_open(struct inode *inode, struct file *file){
return single_open(file, mem_map_show, NULL);
}
struct file_operations mem_map_fops = {
.owner = THIS_MODULE,
.open = mem_map_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init mem_map_init(void){
printk(KERN_INFO "Loaded mem_map modulen");
proc_file = proc_create("mem_map", 0, NULL, &mem_map_fops);
if(!proc_file){
printk(KERN_ALERT "Error: Could not initialize /proc/mem_map");
return -ENOMEM;
}   
return 0;
}
static void __exit mem_map_exit(void){
remove_proc_entry("mem_map",NULL);  
printk(KERN_INFO "Proc file unloaded n");
}

/* Declaration of the init and exit functions */
module_init(mem_map_init);
module_exit(mem_map_exit);

如果我理解正确,您想直接从内核模块打印全局mem_map数组的地址。您要查找的指针是全局的,因此它已被导出供您在内核模块中使用。您所要做的就是找到它的符号。

查找导出的符号很容易,通过包含<linux/kallsyms.h>您将能够使用kallsyms_lookup_name()它采用char *并返回它所代表的符号的地址。您现在要做的就是将地址分配给空指针,可能在init函数中。

mem_map = (struct page *) kallsyms_lookup_name("mem_map");

现在,您的mem_map指针实际上指向您正在寻找的mem_map数组。凉。

接下来,您将声明virt_to_phy()并在其中使用__pa()。为什么?您可以简单地在asm/io.h中使用已经声明的virt_to_phys()(并且在您的情况下执行完全相同的操作(。请不要说您正在尝试打印地址,因此正确的printf格式将是%lx而不是%lu

最后但并非最不重要的一点是,您正在检查的页数实际上是get_num_physpages地址的十进制值,这是一个函数。如果要打印get_num_physpages的返回值,则应将其作为函数调用,get_num_physpages()因为现在您的代码打印指向get_num_physpages的指针的值。

这就是我认为您的代码应该的样子:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/mm.h>
#include <linux/kallsyms.h>
#include <asm/io.h>
#define ERROR -1
MODULE_LICENSE("Dual BSD/GPL");
static struct proc_dir_entry* proc_file;
struct page *mem_map;
int mem_map_show(struct seq_file *m, void *v)
{
int ret_val = 0;
printk(KERN_INFO "Proc file readn");
ret_val =  seq_printf(m, "mem_map virt addr:t0x%pn", mem_map);
ret_val += seq_printf(m, "mem_map phys addr:t0x%016llxn", ((unsigned long long) virt_to_phys((volatile void *) mem_map)));
ret_val += seq_printf(m, "mem_map phys pages:t%lun", (long unsigned int) get_num_physpages());
return ret_val;
}
static int mem_map_open(struct inode *inode, struct file *file)
{
return single_open(file, mem_map_show, NULL);
}
struct file_operations mem_map_fops = {
.owner = THIS_MODULE,
.open = mem_map_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init mem_map_init(void)
{
printk(KERN_INFO "Loaded mem_map modulen");
mem_map = (struct page *) kallsyms_lookup_name("mem_map");
if (!mem_map) {
printk(KERN_ALERT "Error: Unable to find address of global 'mem_map'n");
return ERROR;
}
proc_file = proc_create("mem_map", 0, NULL, &mem_map_fops);
if (!proc_file) {
printk(KERN_ALERT "Error: Could not initialize /proc/mem_mapn");
return -ENOMEM;
}
return 0;
}
static void __exit mem_map_exit(void)
{
remove_proc_entry("mem_map",NULL);
printk(KERN_INFO "Proc file unloadedn");
}

/* Declaration of the init and exit functions */
module_init(mem_map_init);
module_exit(mem_map_exit);

更具体地说,如果您想遵守procfs中的值的打印方式,我会实现mem_map_show

,如下所示:
int mem_map_show(struct seq_file *m, void *v)
{
int ret_val = 0;
ret_val =  seq_printf(m, "0x%p 0x%016llx %lun",
mem_map, 
((unsigned long long) virt_to_phys((volatile void *) mem_map)),
(long unsigned int) get_num_physpages());
return ret_val;
}

最新更新