C 为页表遍历编译内核时出错

C 为页表遍历编译内核时出错,c,linux-kernel,virtual-memory,page-tables,C,Linux Kernel,Virtual Memory,Page Tables,我正在做一个书桌散步。当我准备更新内核时,出现了一个错误: kernel/sys.c: In function ‘__do_sys_get_page_info’: kernel/sys.c:2745:23: error: passing argument 1 of ‘pud_offset’ from incompatible pointer type [-Werror=incompatible-pointer-types] pud = pud_offset(pgd, vmpage);

我正在做一个书桌散步。当我准备更新内核时,出现了一个错误:

kernel/sys.c: In function ‘__do_sys_get_page_info’:
kernel/sys.c:2745:23: error: passing argument 1 of ‘pud_offset’ from incompatible pointer type [-Werror=incompatible-pointer-types]
      pud = pud_offset(pgd, vmpage);
                       ^
In file included from ./include/linux/mm.h:99:0,
                 from kernel/sys.c:19:
./arch/x86/include/asm/pgtable.h:905:22: note: expected ‘p4d_t * {aka struct <anonymous> *}’ but argument is of type ‘pgd_t * {aka struct <anonymous> *}’
 static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address)
                      ^
kernel/sys.c:在函数“\u do\u sys\u get\u page\u info”中:
kernel/sys.c:2745:23:错误:从不兼容的指针类型传递'pud_offset'的参数1[-Werror=不兼容的指针类型]
pud=pud_偏移量(pgd,vmpage);
^
在包含自./include/linux/mm.h:99:0的文件中,
从kernel/sys.c:19:
/arch/x86/include/asm/pgtable.h:905:22:注意:应为“p4d_t*{aka struct*}”,但参数的类型为“pgd_t*{aka struct*}”
静态内联pud_t*pud_偏移量(p4d_t*p4d,无符号长地址)
^
这是使用代码的地方:

....
int loc, ref, dirty;
struct vm_area_struct *vma;
unsigned long vmpage;
struct mm_struct *task_mm = task->mm;
if ((task_mm && task_mm->mmap))
{
    int i;
    pgd_t *pgd;
    pud_t *pud;
    pmd_t *pmd;
    pte_t *ptep, pte;

    vma = task_mm->mmap;

    while (vma)
    {
        for (vmpage = vma->vm_start, i = 1; vmpage < vma->vm_end; vmpage += PAGE_SIZE, i++)
        {
            pgd = pgd_offset(task_mm, vmpage);
            if (pgd_none(*pgd) || pgd_bad(*pgd))
                return 0;

            pud = pud_offset(pgd, vmpage);
            if (pud_none(*pud) || pud_bad(*pud))
                return 0;

            pmd = pmd_offset(pud, vmpage);
            if (pmd_none(*pmd) || pmd_bad(*pmd))
                return 0;

            ptep = pte_offset_kernel(pmd, vmpage);
            if (!ptep)
                return 0;

            pte = *ptep;
            ...
}
。。。。
int loc,ref,dirty;
结构vm_区域_结构*vma;
无符号长页;
结构mm_结构*task_mm=task->mm;
如果((任务-&任务->mmap))
{
int i;
pgd_t*pgd;
布丁;
pmd_t*pmd;
私人有限公司,私人有限公司;
vma=任务\u mm->mmap;
while(vma)
{
对于(vmpage=vma->vmu开始,i=1;vmpagevmu结束;vmpage+=页面大小,i++)
{
pgd=pgd_偏移量(任务毫米,vmpage);
如果(pgd_无(*pgd)| pgd_坏(*pgd))
返回0;
pud=pud_偏移量(pgd,vmpage);
如果(pud_none(*pud)| pud_bad(*pud))
返回0;
pmd=pmd_偏移量(pud,vmpage);
if(pmd_无(*pmd)| pmd_坏(*pmd))
返回0;
ptep=pte_偏移量_内核(pmd,vmpage);
如果(!ptep)
返回0;
pte=*ptep;
...
}
我查找了错误和注释,但没有找到任何关于解决此问题的方法。这是一个众所周知的问题还是我做错了什么


更新*

我最近遇到了同样的问题,我发现就像pgd_偏移和pud_偏移一样,也有一个p4d_偏移。将其放在pgd和pud之间:

pgd_t *pgd;
p4d_t* p4d;
pud_t *pud;
pmd_t *pmd;
pte_t *ptep, pte;

...

pgd = pgd_offset(task_mm, vmpage);
if (pgd_none(*pgd) || pgd_bad(*pgd))
    return 0;

p4d = p4d_offset(pgd, vmpage);
if (p4d_none(*p4d) || p4d_bad(*p4d))
    return 0;

pud = pud_offset(p4d, vmpage);
if (pud_none(*pud) || pud_bad(*pud))
    return 0;

...
编辑:以下是有关附加级别的一些信息:


它已经在内核版本4.11中实现。

vmpage变量的类型是什么?看起来这种类型的宽度小于地址类型的宽度。我更新了代码,还添加了我得到的其他警告。关于
vmpage
未使用的警告。但我不知道我怎么没有使用它。明白了。Expression
int I=1,vmpage=vma->vmu start;
实际上定义了两个类型为
int
的变量:
i
vmpage
。此声明隐藏了
vmpage
for循环的
之前的声明。这就是为什么您会收到警告
未使用的变量“vmpage”
和关于“移位计数”的警告.我编辑了代码。由于
pud\u offset
功能,它显示错误。