2017-08-21 1 views
1

J'essaye d'imprimer l'adresse virtuelle de mem_map, l'adresse physique de mem_map et le nombre de page de structure maintenant. donc j'ai essayé d'exécuter le code de this article, mais il semblait que cela ne montre pas l'adresse correcte. Pourriez-vous me dire comment je peux résoudre ce problème?Comment imprimer les informations de mem_map en utilisant le fichier proc?

Voici le résultat de l'exécution.

mem_map virt adr: (null) mem_map Phys Adr: 131941395333120 mem_map phys pages: 18446744072101367984

J'utilise Ubuntu12.04 (64 bits) et la version du noyau est 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); 
+0

Vous déclarez une variable 'mem_map' qui est un pointeur, et exporte même son symbole, mais où l'initialisez-vous? Qu'est-ce que vous voulez exactement imprimer, l'adresse de quoi? – Quaker

+0

Je pensais que mem_map était initialisé quelque part parce que, d'après l'article que j'avais vu, mem_map n'était pas assigné par quoi que ce soit. C'est pourquoi j'étais confus. mais votre point est très évident.Merci de m'aider – Angesan

Répondre

0

Si je comprends bien, vous voulez imprimer l'adresse du tableau global mem_map, à partir de votre module de noyau. Le pointeur que vous recherchez est global, donc it has already been exported pour que vous puissiez l'utiliser dans votre module noyau. Tout ce que vous avez à faire est de trouver son symbole.

Trouver un symbole exporté est facile, en incluant <linux/kallsyms.h> vous aurez le pouvoir d'utiliser kallsyms_lookup_name() qui prend un char * et retourne l'adresse du symbole qu'il représente. Tout ce que vous avez à faire maintenant est d'assigner l'adresse au pointeur vide, éventuellement dans votre fonction init.

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

Maintenant, votre pointeur mem_map en fait les points au tableau mem_map que vous êtes après. Cool. Ensuite, vous déclarez virt_to_phy() et utilisez __pa() à l'intérieur. Pourquoi? Vous pouvez simplement utiliser virt_to_phys() qui est déjà déclaré (et faire exactement la même chose dans votre cas) dans asm/io.h. S'il vous plaît ne pas que vous essayez d'imprimer une adresse, donc le bon format printf serait %lx au lieu de %lu.

Dernier point, mais non des moindres, ridicule, le nombre de pages que vous examinez est en fait la valeur décimale de l'adresse de get_num_physpages, qui est une fonction. Si vous souhaitez imprimer la valeur de retour de get_num_physpages vous devriez l'appeler comme une fonction, get_num_physpages() parce que maintenant votre code imprime la valeur du pointeur à get_num_physpages.

Voilà comment je pense que votre code devrait ressembler:

#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); 

et plus précisément, si vous voulez respecter la façon dont les valeurs en procfs sont imprimées, je mettre en œuvre mem_map_show un peu comme ceci:

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; 
} 
+0

Cela fonctionne complètement pour moi. Ce que vous avez dit fait le sens. Je l'apprécie vraiment. Chaque fois que je trouve la réponse à propos de Linux, je ne la trouve pas. Pourriez-vous recommander un site ou des livres pour la programmation du noyau Linux si possible? – Angesan

+0

sûr, à mon avis, ces 3 livres sont essentiels, ["Linux Kernel Development", Robert Love] (https://www.amazon.com/Linux-Kernel-Development-Robert-Love/dp/0672329468), [" Pilotes de périphériques Linux ", Jonathan Corbet] (https://www.amazon.com/Linux-Device-Drivers-Jonathan-Corbet/dp/0596005903/) et [" Comprendre le noyau Linux ", Daniel P. Bovet] (https : //www.amazon.com/Understanding-Linux-Kernel-Third-Daniel/dp/0596005652). En outre, lire et _understand_ le code. Faites usage de [LXR] (http://lxr.free-electrons.com). – Quaker

+0

J'ai des préoccupations mineures ici. 1) quoi de neuf avec ERROR de -1 2) le symbole mem_map peut finir par aliaser le global. En fait, les chances sont kallsyms_lookup renvoie déjà à la place de celui attendu. Je dois également noter que toute la cession semble super poisson. –