我正在尝试浏览Linux中某个进程的页表。在内核模块中,我实现了以下功能:
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是进程地址空间中的虚拟地址:
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调用获取例如:
dmesg
[ 1721.437104] Valid pgd [ 1721.437108] Valid pud [ 1721.437108] Valid pmd [ 1721.437110] page frame struct is @ c17d9b80
那么,为什么该过程无法正确完成“ ioctl”调用?也许我必须在浏览页面表之前锁定一些东西?
我正在使用内核2.6.35-22和三级页表。
谢谢你们!
pte_unmap(ptep);
标签刚好消失了。尝试以这种方式更改代码:
... page = pte_page(pte); if (page) printk(KERN_INFO "page frame struct is @ %p", page); pte_unmap(ptep); out: