我正在尝试在linux中浏览一个进程的页表。 在一个内核模块中,我实现了以下function:
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; }
这个函数是从ioctl调用的, addr是进程地址空间中的虚拟地址:
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; }
奇怪的是,在用户空间进程中调用ioctl ,这段错误…但似乎我正在寻找页表条目的方式是正确的,因为用dmesg我获得例如每个ioctl调用:
[ 1721.437104] Valid pgd [ 1721.437108] Valid pud [ 1721.437108] Valid pmd [ 1721.437110] page frame struct is @ c17d9b80
那么,为什么这个过程不能完成正确的'ioctl'调用呢? 也许我必须在浏览页面表之前locking一些东西?
劫持系统调用
如何在Linux内核中使用bio请求来读取扇区
Linux内核中的调度algorithm
在内核模块中实现cpu扩展
我正在使用内核2.6.35-22和三级页表。
谢谢你们!
哪里可以findglibc源代码中的select()源代码?
Fedora 19的x86_64内核版本与内核源码不同
如何处理ASID的情况在Linux内核中用完了?
通过内核模块轮询循环设备
哪里可以findLinux设备驱动程序第三版的示例源文件?
pte_unmap(ptep);
... page = pte_page(pte); if (page) printk(KERN_INFO "page frame struct is @ %p",page); pte_unmap(ptep); out:
看看/proc/<pid>/smaps文件系统,你可以看到用户空间的内存:
cat smaps bfa60000-bfa81000 rw-p 00000000 00:00 0 [stack] Size: 136 kB RSS: 44 kB
以及如何打印是通过fs/proc/task_mmu.c (来自内核源):
http://lxr.linux.no/linux+v3.0.4/fs/proc/task_mmu.c
if (vma->vm_mm && !is_vm_hugetlb_page(vma)) walk_page_range(vma->vm_start,vma->vm_end,&smaps_walk); show_map_vma(m,vma.....); seq_printf(m,"Size: %8lu kBn" "RSS: %8lu kBn" "Pss: %8lu kBn"
你的函数有点像walk_page_range()。 看着walk_page_range(),你可以看到smaps_walk结构在走路时不应该改变:
http://lxr.linux.no/linux+v3.0.4/mm/pagewalk.c#L153 For eg: } 201 if (walk->pgd_entry) 202 err = walk->pgd_entry(pgd,addr,next,walk); 203 if (!err && 204 (walk->pud_entry || walk->pmd_entry || walk->pte_entry
如果步行是改变的,那么上述所有的检查可能会变得不一致。
所有这些只是意味着在走页面表时必须锁定mmap_sem:
if (!down_read_trylock(&mm->mmap_sem)) { /* * Activate page so shrink_inactive_list is unlikely to unmap * its ptes while lock is dropped,so swapoff can make progress. */ activate_page(page); unlock_page(page); down_read(&mm->mmap_sem); lock_page(page); }
然后解锁:
up_read(&mm->mmap_sem);
当然,当你在你的内核模块中发布pagetable的printk()时,内核模块会运行在insmod进程的进程上下文中(只需要打印“comm”,你就可以看到“insmod”),这意味着mmap_sem是锁定,这也意味着进程没有运行,因此在进程完成之前没有控制台输出(所有的printk()输出都只进入内存)。
听起来合乎逻辑?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。