Tôi đang cố điều hướng các bảng trang cho một quy trình trong linux. Trong một mô-đun hạt nhân tôi nhận ra các chức năng sau:Bảng trang đi bộ của quy trình trong 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;
}
Chức năng này được gọi là từ ioctl
và addr
là một địa chỉ ảo trong không gian địa chỉ tiến trình:
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;
}
Điều lạ là gọi ioctl
trong một quá trình không gian người dùng, điều này segfaults ... nhưng có vẻ như là cách tôi đang tìm mục nhập bảng trang là chính xác vì với dmesg
tôi có được ví dụ cho mỗi ioctl
gọi:
[ 1721.437104] Valid pgd
[ 1721.437108] Valid pud
[ 1721.437108] Valid pmd
[ 1721.437110] page frame struct is @ c17d9b80
Vậy tại sao quá trình không thể hoàn thành chính xác cuộc gọi 'ioctl'? Có lẽ tôi phải khóa một cái gì đó trước khi điều hướng các bảng trang?
Tôi đang làm việc với hạt nhân 2.6.35-22 và ba bảng trang cấp.
Cảm ơn tất cả!
Có thể ioctl syscall trả về thành công và mã được phân đoạn sau đó không? –
Không vì syscall ioctl là lệnh cuối cùng trong 'main' trước' return'.Nếu tôi nhận xét 'ioctl' thì quá trình này không phân biệt. – MirkoBanchi
Tại sao bạn ẩn phần mà bạn sử dụng địa chỉ của 'struct page'? Bạn có chắc chắn rằng segfaults của bạn không đến từ đây? Bạn đã thử gỡ lỗi này trên qemu chưa? –