微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在Linux中进行进程的页面表

我正在尝试在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一些东西?

如何获取内核转储中的Section对象的内容

劫持系统调用

如何在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] 举报,一经查实,本站将立刻删除。

相关推荐