linux - How to print the information of mem_map using proc file? -
i'm trying print virtual address of mem_map,physical address of mem_map , number of struct page now. tried running code of this article,but seemed didn't show correct address. tell me how can fix this?
below result of execution.
mem_map virt addr: (null) mem_map phys addr: 131941395333120 mem_map phys pages: 18446744072101367984
i'm using ubuntu12.04(64bit) , kernel version 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> // basic filesystem #include <linux/proc_fs.h> // proc filesystem #include <linux/seq_file.h> // 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 module\n"); proc_file = proc_create("mem_map", 0, null, &mem_map_fops); if(!proc_file){ printk(kern_alert "error: 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 init , exit functions */ module_init(mem_map_init); module_exit(mem_map_exit);
if understand correctly, want print address of global mem_map
array, right kernel module. pointer you're looking global ,therefore it has been exported use in kernel module. have find its' symbol.
finding exported symbol easy, including <linux/kallsyms.h>
you'll have power of using kallsyms_lookup_name()
takes char *
, returns address of symbol represents. have now, assigning address empty pointer, possibly in init
function.
mem_map = (struct page *) kallsyms_lookup_name("mem_map");
now mem_map
pointer points mem_map
array you're after. cool.
next, you're declaring virt_to_phy()
, using __pa()
inside it. why? can use virt_to_phys()
declared (and doing same in case) in asm/io.h
. please not you're trying print address, therefore right printf
format %lx
instead of %lu
.
last not least, ridiculous number of pages you're examining decimal value of address of get_num_physpages
, function. if wish print return value of get_num_physpages
should call function, get_num_physpages()
because code prints value of pointer get_num_physpages
.
this how think code should have looked like:
#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 read\n"); ret_val = seq_printf(m, "mem_map virt addr:\t0x%p\n", mem_map); ret_val += seq_printf(m, "mem_map phys addr:\t0x%016llx\n", ((unsigned long long) virt_to_phys((volatile void *) mem_map))); ret_val += seq_printf(m, "mem_map phys pages:\t%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 module\n"); mem_map = (struct page *) kallsyms_lookup_name("mem_map"); if (!mem_map) { printk(kern_alert "error: unable 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: not initialize /proc/mem_map\n"); 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 init , exit functions */ module_init(mem_map_init); module_exit(mem_map_exit);
and more specifically, if want comply how values in procfs
printed, implement mem_map_show
this:
int mem_map_show(struct seq_file *m, void *v) { int ret_val = 0; ret_val = seq_printf(m, "0x%p 0x%016llx %lu\n", mem_map, ((unsigned long long) virt_to_phys((volatile void *) mem_map)), (long unsigned int) get_num_physpages()); return ret_val; }
Comments
Post a Comment