如果只是需要大致地判断范围,可以参考内核\linux-3.4.104\Documentation\x86\x86_64\mm.txt中的对各个段的分配的描述。
但是如果需要更加精确地判断,就需要根据内核页表,一级一级地查找,查看是否存在对应的物理地址(内核态的地址不存在SWAP的问题),下面是内核代码段(针对X86-64,有修改)
int kern_addr_valid(unsigned long address)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
unsigned long high_bits = ((long)address) >> 47;
if (high_bits != 0 && high_bits != -1UL)
return 0;/*原因见INTEL相关文档*/
/*swapper_pg_dir对应的符号init_level4_pgt在有的版本没有导出
需要用kallsyms_lookup_name获取到该符号的地址*/
pgd = swapper_pg_dir + pgd_index(address);
if (pgd_present(*pgd))
return 0;
pud = pud_offset(pgd, address);
if (pud_present(*pud))
return 0;
if (pud_large(*pud))
return pfn_valid(pud_pfn(*pud));
pmd = pmd_offset(pud, address);
if (pmd_present(*pmd))
return 0;
if (pmd_large(*pmd))
return pfn_valid(pmd_pfn(*pmd));
pte = pte_offset_kernel(pmd, address);
if (pte_present(*pte))
return 0;
return pfn_valid