Pied de page des tableaux d'un processus dans Linux
je suis en train de naviguer sur la page, les tableaux d'un processus dans linux. Dans un module du noyau, j'ai réalisé la fonction suivante:
static struct page *walk_page_table(unsigned long addr)
{
pgd_t *pgd;
pte_t *ptep, pte;
pud_t *pud;
pmd_t *pmd;
struct page *page = NULL;
struct mm_struct *mm = current->mm;
pgd = pgd_offset(mm, addr);
if (pgd_none(*pgd) || pgd_bad(*pgd))
goto out;
printk(KERN_NOTICE "Valid pgd");
pud = pud_offset(pgd, addr);
if (pud_none(*pud) || pud_bad(*pud))
goto out;
printk(KERN_NOTICE "Valid pud");
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd) || pmd_bad(*pmd))
goto out;
printk(KERN_NOTICE "Valid pmd");
ptep = pte_offset_map(pmd, addr);
if (!ptep)
goto out;
pte = *ptep;
page = pte_page(pte);
if (page)
printk(KERN_INFO "page frame struct is @ %p", page);
out:
return page;
}
Cette fonction est appelée à partir de la ioctl
et addr
est une adresse virtuelle dans l'espace d'adressage du processus:
static int my_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long addr)
{
struct page *page = walk_page_table(addr);
...
return 0;
}
La chose étrange est que l'appel à ioctl
dans un espace utilisateur, c'est un processus de segmentation...mais il semble que la façon dont je suis à la recherche de la page d'entrée de la table est correcte car avec dmesg
- je obtenir par exemple pour chaque ioctl
appel:
[ 1721.437104] Valid pgd
[ 1721.437108] Valid pud
[ 1721.437108] Valid pmd
[ 1721.437110] page frame struct is @ c17d9b80
Alors pourquoi le processus ne peut pas être effectuée correcly le "ioctl' appel? J'ai peut-être pour verrouiller quelque chose avant de naviguer dans la page tables?
Je suis en train de travailler avec le noyau 2.6.35-22 et trois niveaux de tables de pages.
Merci à vous tous!
- Est-il possible que ioctl syscall retourne avec succès, et le code est segfaulting après cela?
- Non, car le ioctl syscall est la dernière instruction dans
main
avantreturn
. Si j'ai fait un commentaireioctl
le processus n'a pas d'erreur de segmentation. - Pourquoi avez-vous cacher la partie où vous utilisez l'adresse de la
struct page
? Êtes-vous sûr que vos erreurs de segmentation ne vient pas de là? Avez-vous essayé de débogage ce sur qemu? - Après l'appel de
walk-page_table
j'en fais unprintk
sipage
estNULL
. J'ai essayé aussi de ne garder que l'appel àwalk_page_table
mais le processus encore des erreurs de segmentation. Peut-être que oui, le moyen le plus rapide à découvrir le problème est de débogage. Merci Quentin. - Compiler le code avec le débogage et la force d'une trace de la pile au cours de décharges, de sorte que vous devez absolument savoir ce qui se passe. Ou utiliser kgdb. Sont également positifs pour vous assurer que vous n'êtes pas à l'aide de la nouvelle unlocked_ioctl caractéristique de la les noyaux récents?
- Je n'ai jamais utilisé kgdb. Je vais vous permettra de déboguer un noyau UML avec gdb. Cependant, je ne suis pas en utilisant
unlocked_ioctl
: noyau 2.6.35 a encoreioctl
pointeur de fonction dansstruct file_operations
. Grâce sessyargc.jp!
Vous devez vous connecter pour publier un commentaire.
manque juste avant de l'étiquette. Essayez de modifier le code de cette façon:
pte_offset_map
fait unkmap
.Regarder
/proc/<pid>/smaps
système de fichiers, vous pouvez voir l'espace utilisateur de la mémoire:et comment il est imprimé est via
fs/proc/task_mmu.c
(à partir des sources du noyau):http://lxr.linux.no/linux+v3.0.4/fs/proc/task_mmu.c
Et votre fonction est un peu comme celle de walk_page_range(). La recherche dans walk_page_range (), vous pouvez voir que le smaps_walk structure n'est pas censé changer alors qu'il est en marche:
Si le contenu de la mémoire ont été modifier, puis de tout ce qui précède que la vérification obtenir incompatible.
Tous ces tout simplement dire que vous devez verrouiller le mmap_sem lors de la marche de la table des pages:
et ensuite par le déverrouillage:
Et bien sûr, lorsque vous émettez printk() de la pagetable à l'intérieur de votre module de noyau, le noyau du module est en cours d'exécution dans le cadre de votre insmod (le printk la "comm" et vous pouvez voir "insmod") qui a le sens de la mmap_sem est la serrure, il signifie également le processus n'est PAS en cours d'exécution, et donc il n'y a pas de sortie de la console jusqu'à la fin du processus (tous les printk() sortie passe à mémoire uniquement).
Semble logique?
mmap_sem
avant la première instruction qui lit la page tables, mais ne fonctionne pas...la même Segmentation fault erreur. Cependant quand je l'appellewalk_page_table
je ne suis pas dans le contexte du processusinsmod
: j'appelle ça de l'intérieurmy_ioctl
je suis donc dans le contexte de processus invoquantioctl
syscall. Cela pourrait-il faire une différence?