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

时间:2017-08-21 08:04:35

标签: linux linux-kernel

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

以下是执行结果。

mem_map virt addr:(null) mem_map phys addr:131941395333120 mem_map phys pages: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 module\n");
    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);

1 个答案:

答案 0 :(得分:0)

如果我理解正确,您希望直接从内核模块打印全局 mem_map数组的地址。您正在寻找的指针是全局的,因此您可以在内核模块中使用it has already been exported。你所要做的就是找到它的&#39;符号

通过添加<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()并在其中使用virt_to_phys()。为什么?您只需使用asm/io.h中已声明(并在您的情况下完全相同)的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 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 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_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 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 %lu\n", mem_map, ((unsigned long long) virt_to_phys((volatile void *) mem_map)), (long unsigned int) get_num_physpages()); return ret_val; } ,就像这样:

import pandas as pd 
from StringIO import StringIO 

data = """
productid|feature1|value1|feature2|value2|feature3|value3
100001|weight|130g|||price|$140.50
100002|weight|200g|pieces|12pcs|dimensions|150X75cm
100003|dimensions|70X30cm|price|$22.90||
100004|price|$12.90|manufacturer|ABC|calories|556Kcal
100005|calories|1320Kcal|dimensions|20X20cm|manufacturer|XYZ
"""
# simulate reading from a csv file
df= pd.read_csv(StringIO(data), sep="|")

# pivot all (productid, feature{x}, value{x}) tuples into a tabular dataframe 
# and append them to the following list 
converted = []

# you can construct this programmatically (out of scope for now) 
mapping = {"feature1": "value1", "feature2": "value2","feature3": "value3"}

# iteritems() become items() in python3
for feature, values in mapping.iteritems():
        # pivot  (productid, feature{x}, value{x}) into a tabular dataframe 
        # columns names : feature{x} 
        # values: value{x}  
        df1 = pd.pivot_table(df, values=values, index=["productid"], columns=[feature], aggfunc=lambda x: x.iloc[0]) 
        # remove the name from the pivoted dataframe to get a standard dataframe 
        df1.columns.name = None
        # keep productid in the dataframe as a column 
        df1.reset_index(inplace=True)
        converted.append(df1)

# merge all dataframe in the list converted into one dataframe 
final_df1 = converted[0] 
for index,df_ in enumerate(converted[1:]):
        final_df1 = pd.merge(final_df1, df_, how="outer")

import numpy as np 
# replace None with np.nan so groupby().first() take the first none NaN vaues 
final_df1.fillna(value=np.nan, inplace=True)
# format the data to be iso to what the OP wants  
final_df1 = final_df1.groupby("productid", as_index=False).first()

print(final_df1)