linux内核地址有效性判断方法
2014-11-30 16:23
155 查看
如果只是需要大致地判断范围,可以参考内核\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(pte_pfn(*pte)); }
以上代码段基本上和内核的中有关于对high_bits的做法,是基于X86-64架构对64位线性地址的处理,当前的架构采用9-9-9-9-12的模式,只是用了48位,就规定:高16bits(48-63)必须和第47bits保持一致。详细的说明参见《Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 1:Basic Architecture》3.3.7.1 Canonical Addressing:
Intel 64 architecture defines a 64-bit linear address. Implementations can support less. The first implementation of IA-32 processors with Intel 64 architecture supportsa 48-bit linear address. This means a canonical address must have bits 63 through 48 set to zeros or ones (depending on whether bit 47 is a zero or one).
如果违反该规则,CPU会检查到该错误并发起一个General protection fault
注意:以上的代码,是判断一个地址是否可以读,当然只是保证读的话不产生page fault,可以和magic值一起进一步确认。如果要判断是否可写,需要进一步检查
相关文章推荐
- Linux 2.6版内核中通过模块获取sys_call_table地址的方法
- Linux升级内核虽然我按照上面的方法没有成功,原因是镜像地址下载太慢导致的,后续知道怎么解决后在评论中给出方案
- Linux 2.6版内核中通过模块获取sys_call_table地址的方法
- linux 内核进程与用户进程的通信 方法一 使用sockopt与内核交换数据
- Linux-2.6内核移植过程中常见问题及解决方法
- Linux 2.6内核中提高网络I/O性能的新方法-epoll
- linux 内核进程与用户进程的通信 方法一 使用sockopt与内核交换数据
- 解析Linux内核获取当前进程指针的方法
- (转贴)Linux 2.6内核中提高网络I/O性能的新方法epoll
- Linux内核启动地址的确定
- linux2.6内核编译方法详述
- windows及Linux系统下获取IP及MAC地址的方法
- linux内核2.6中设备模块编程的解决方法
- Linux中判断平台是大端或小端的方法
- 获取内核地址的简单方法
- linux内核启动地址的确定
- Linux详细编译内核方法(1)
- Linux详细编译内核方法(2)
- 编译Linux系统内核的方法步骤
- 查看Linux内核、CPU、内存及各组件版本的命令和方法