设为首页 收藏本站
查看: 282|回复: 0

[经验分享] 关于内核模块的挂载后的最终虚拟地址(Linux-3.0)

[复制链接]
发表于 2015-12-11 09:00:59 | 显示全部楼层 |阅读模式
最近在重新学习LDD3,做最基础的底层原理学习。在挂载Hello_world模块的测试中,我发现对于ARM构架的设备,模块挂载后,模块中包含的函数和静态变量的虚拟地址不在3G(0xC0000000)以上,而是3G以下一点的位置(大概在0xBF000000),所以我通过源码了解了一下其中的原因。


首先,我们必须知道模块的挂载过程,这些较为复杂,可以参考《深入Linux内核构架》的《第七章 模块》。简单的说就是module-init-tool中的insmod的程序通过系统调用(in kernle/module.c):


  • SYSCALL_DEFINE3(init_module, void __user *, umod,
  •         unsigned long, len, const char __user *, uargs)

-------------------------------------------------------------------------------
    PS : 其中SYSCALL_DEFINE3是内核用于生成系统调用函数名的宏():
      

  • #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
  • ......
  • #ifdef CONFIG_FTRACE_SYSCALLS
  • #define SYSCALL_DEFINEx(x, sname, ...)\
  • static const char *types_##sname[] = {\
  • __SC_STR_TDECL##x(__VA_ARGS__)\
  • };\
  • static const char *args_##sname[] = {\
  • __SC_STR_ADECL##x(__VA_ARGS__)\
  • };\
  • SYSCALL_METADATA(sname, x);\
  • __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
  • #else
  • #define SYSCALL_DEFINEx(x, sname, ...)\
  • __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
  • #endif

  • #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS

  • #define SYSCALL_DEFINE(name) static inline long SYSC_##name

  • #define __SYSCALL_DEFINEx(x, name, ...)\
  • asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__));\
  • static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__));\
  • asmlinkage long SyS##name(__SC_LONG##x(__VA_ARGS__))\
  • {\
  • __SC_TEST##x(__VA_ARGS__);\
  • return (long) SYSC##name(__SC_CAST##x(__VA_ARGS__));\
  • }\
  • SYSCALL_ALIAS(sys##name, SyS##name);\
  • static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__))

  • #else /* CONFIG_HAVE_SYSCALL_WRAPPERS */

  • #define SYSCALL_DEFINE(name) asmlinkage long sys_##name
  • #define __SYSCALL_DEFINEx(x, name, ...)\
  • asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))

  • #endif /* CONFIG_HAVE_SYSCALL_WRAPPERS */

所以生成的系统调用名字为:sys_init_module
-------------------------------------------------------------------------------------------
在这个系统调用中,按模块的各个sections分配空间,而关于模块最终地址空间的调用过程是:
load_module-->layout_and_allocate-->move_module-->module_alloc_update_bounds-->module_alloc


所有关键就在module_alloc其中的实现,而这个函数的实现是构架依赖的:
(1)有些构架是直接调用vmalloc,所有模块最终的虚拟地址空间应该是在内核的虚拟地址空间中的。
(2)还有些构架(X86和ARM等)调用的是:__vmalloc_node_range
例如ARM中:(arch/arm/kernel/module.c)


  • void *module_alloc(unsigned long size)
  • {
  •     return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
  •                 GFP_KERNEL, PAGE_KERNEL_EXEC, -1,
  •                 __builtin_return_address(0));
  • }

所有这个虚拟地址的范围就应该在: MODULES_VADDR----MODULES_END


对于这两个宏的定义:(arch/arm/include/asm/memory.h)


  • /*
  • * PAGE_OFFSET - 内核映像(解压后)运行的起始虚拟地址
  • * TASK_SIZE - 一个用户空间 task 的大小最大值.
  • * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
  • */
  • #define PAGE_OFFSETUL(CONFIG_PAGE_OFFSET)
  • #define TASK_SIZE(UL(CONFIG_PAGE_OFFSET) - UL(0x01000000))
  • #define TASK_UNMAPPED_BASE(UL(CONFIG_PAGE_OFFSET) / 3)

  • /*
  • * The maximum size of a 26-bit user space task.
  • */
  • #define TASK_SIZE_26UL(0x04000000)

  • /*
  • * The module space lives between the addresses given by TASK_SIZE
  • * and PAGE_OFFSET - it must be within 32MB of the kernel text.
  • */
  • #ifndef CONFIG_THUMB2_KERNEL
  • #define MODULES_VADDR(PAGE_OFFSET - 16*1024*1024)
  • #else
  • /* smaller range for Thumb-2 symbols relocation (2^24)*/
  • #define MODULES_VADDR(PAGE_OFFSET - 8*1024*1024)
  • #endif

  • #if TASK_SIZE > MODULES_VADDR
  • #error Top of user space clashes with start of module space
  • #endif

  • /*
  • * The highmem pkmap virtual space shares the end of the module area.
  • */
  • #ifdef CONFIG_HIGHMEM
  • #define MODULES_END(PAGE_OFFSET - PMD_SIZE)
  • #else
  • #define MODULES_END(PAGE_OFFSET)
  • #endif

正常情况下PAGE_OFFSET会被定义为0xc0000000,所以  
MODULES_VADDR----MODULES_END ---> 0xBF000000----0xC0000000


这样就解释了为什么模块挂载后的最终虚拟地址空间不在正常的内核虚拟地址空间0xC0000000之上了~~~~

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-149474-1-1.html 上篇帖子: 好文转载:Linux内核中的中断栈与内核栈的补充说明 下篇帖子: CentOS_6.5_X86 配置多网卡汇聚(bonding)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表