Linux内核模块采用专用的地址空间,有一定的固定大小,具体可以通过起机dmesg信息里的字段来确认

Memory: 245540K/262144K available (3043K kernel code, 1665K rwdata, 1112K rodata, 176K init, 6356K bss, 16604K reserved, 0K cma-reserved)

Virtual kernel memory layout:

vector : 0xffff0000 - 0xffff1000 ( 4 kB)

fixmap : 0xffc00000 - 0xfff00000 (3072 kB)

vmalloc : 0xd0800000 - 0xff000000 ( 744 MB)

lowmem : 0xc0000000 - 0xd0000000 ( 256 MB)

modules : 0xbe600000 - 0xc0000000 ( 26 MB) <<< 模块地址空间

.text : 0xc0018000 - 0xc04272b0 (4157 kB)

.init : 0xc0428000 - 0xc0454000 ( 176 kB)

.data : 0xc0454000 - 0xc05f45c0 (1666 kB)

.bss : 0xc05f45c0 - 0xc0c295ec (6357 kB)

所需空间大小

模块在加载时,会调用module_alloc()来申请一块内存来存放模块的内容,需要的大小如下:

​ 代码段(.text) + 未初始化全局或静态变量(.bss) + 已初始化全局或静态变量(.data)

关联源码

模块在加载时,内核会调用module_alloc()来申请足够的内存来存放模块内容。module_alloc有2处定义:

kernel/module.c: 定义一个弱符号module_alloc(),若arch下没有定义强符号,就使用它,实际基本没什么用

void * __weak module_alloc(unsigned long size)

{

return vmalloc_exec(size);

}

arch/arm/kernel/module.c: 基于CPU平台来定义module_alloc(),属于强符号

#ifdef CONFIG_MMU

void *module_alloc(unsigned long size)

{

return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,

GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,

__builtin_return_address(0));

}

#endif

实际范围为MODULES_VADDR~MODULES_END

#define MODULES_END (PAGE_OFFSET)

#define MODULES_VADDR (MODULES_END - 16*1048576)

对于arm平台,默认模块地址空间为16M,修改内核代码,可以扩大到28M

https://patchwork.kernel.org/project/linux-arm-kernel/patch/002001cf07a1$fd4bdc10$f7e39430$@lge.com/

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c1f1a7e..cf1fb55 100644

--- a/arch/arm/Kconfig

+++ b/arch/arm/Kconfig

@@ -2257,6 +2257,10 @@ config ARM_CPU_SUSPEND

endmenu

+config MODULES_AREA_SIZE

+ int

+ default 0x1000000

+

source "net/Kconfig"

source "drivers/Kconfig"

diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h

index 6976b03..3396758 100644

--- a/arch/arm/include/asm/memory.h

+++ b/arch/arm/include/asm/memory.h

@@ -32,13 +32,17 @@

#ifdef CONFIG_MMU

+#if CONFIG_MODULES_AREA_SIZE > SZ_32M

+#error Too much space for modules

+#endif

+

/*

* PAGE_OFFSET - the virtual address of the start of the kernel image

* TASK_SIZE - the maximum size of a user space task.

* TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area

*/

-#define PAGE_OFFSET UL(CONFIG_PAGE_OFFSET)

-#define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M))

+#define PAGE_OFFSET UL(CONFIG_PAGE_OFFSET)

+#define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) -

UL(CONFIG_MODULES_AREA_SIZE))

#define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M)

MODULE_PLTS

Linux新的内核引入module PLT(Procedure Link Table)机制,让模块加载使用vmalloc空间的方法,解决模块空间不够用的问题。

变更履历

#ifdef CONFIG_MMU

void *module_alloc(unsigned long size)

{

gfp_t gfp_mask = GFP_KERNEL;

void *p;

/* Silence the initial allocation */

if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS))

gfp_mask |= __GFP_NOWARN;

p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,

gfp_mask, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,

__builtin_return_address(0));

if (!IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || p)

return p;

return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,

GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,

__builtin_return_address(0));

}

#endif

使用方法

配置CONFIG_ARM_MODULE_PLTS=y

配置CONFIG_ARM64_MODULE_PLTS=y

最终的效果如下图所示,模块的地址并不是常见的0xbf打头,而是落在vmalloc区域

image.png

模块空间占用裁减

通过objdump -t命令可以查看模块的所有符号

识别所有符号里的.bss和.data部分,确认是否有大块的变量符号

整改大块的变量符号,将其转变为动态申请的内存形式

linux内核符号地址,Linux内核-模块专用地址空间相关推荐

  1. Linux内核学习--内存管理模块

    Linux内核学习--内存管理模块 首先,Linux内核主要由五个部分组成,他们分别是:进程调度模块.内存管理模块.文件系统模块.进程间通信模块和网络接口模块. 本部分所讲的内存是内存管理模块,其主要 ...

  2. linux 内核空间 sy,在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysf...

    级别: 初级 燚 杨 (), 计算机科学硕士 2006 年 2 月 16 日 本系列文章包括两篇,它们文详细地介绍了 Linux 系统下用户空间与内核空间数据交换的九种方式,包括内核启动参数.模块参数 ...

  3. linux 内核 netfilter 网络过滤模块 (1)-框架

    1. netfilter框架 Netfilter 是Linux内核中进行数据包过滤.连接跟踪.地址转换等的主要实现框架.当我们希望过滤特定的数据包或者需要修改数据包的内容再发送出去,这些动作主要都在n ...

  4. 解析Linux内核的基本的模块管理与时间管理操作---超时处理【转】

    转自:http://www.jb51.net/article/79960.htm 这篇文章主要介绍了Linux内核的基本的模块管理与时间管理操作,包括模块加载卸载函数的使用和定时器的用法等知识,需要的 ...

  5. linux 内核学习11-内核模块参数

    linux 内核学习11-内核模块参数 内核模块作为一个可拓展的动态模块,为Linux内核提供灵活性,所以需要依据不同的场景来传递不同的参数,实现不同的功能 1. 准备工作 #define modul ...

  6. Linux内核设计与实现---模块

    模块 1 构建模块 放在内核源代码树中 放在内核代码外 2 安装模块 3 产生模块依赖性 4 载入模块 5 管理配置选项 6 模块参数 7 导出符号表 Linux内核是模块化组成的,它允许内核在运行时 ...

  7. linux 内核 netfilter 网络过滤模块 (5)-iptables

    iptables是用户态的配置工具,用于实现网络层的防火墙,用户可以通过iptables命令设置一系列的过滤规则,来截获特定的数据包并进行过滤或其他处理. iptables命令通过与内核中的netfi ...

  8. Linux 用户空间和内核空间

    最近在微信群里看到有人提这个问题,然后查了下资料,觉得这篇文章是写得最能让人看懂的,分享给大家. 欢迎大家评论说出自己的见解,让更多的人更容易理解这部分知识. 之前的相关文章 Linux内存,先看这篇 ...

  9. Linux用户态与内核态通信的几种方式(待完善)

    文章目录 1. 内核启动参数 2.模块参数与sysfs 3.sysctl 4.系统调用 5.netlink 6. procfs(/proc) 7.seq_file 8.debugfs 9.relayf ...

  10. 【Linux内核】Linux内核介绍

    Linux学习内核思路 学习过程: Linux内核引导及如何初始化 进程管理.内存管理 内核引导及过程: CPU通电后,首先执行引导程序,引导程序把内核加载到**内存,**然后执行内核,内核初始化完成 ...

最新文章

  1. 利用openssh实现chroot监牢
  2. 【Java基础】对象拷贝
  3. android程序启动动画,Android设置软件启动动画(以及初次安装的几张引导图)
  4. webstorm中vue项目--运行配制
  5. 数据库调优过程(五):物理分表,及写入方案调整
  6. data:image data url 文件上传
  7. python 二叉树中所有距离为k的节点_Redis:从应用到底层,一文帮你搞定
  8. VMware Workstation不可恢复错误: (vcpu-0)
  9. python利用pyhive 连接hive
  10. 被晨光搁浅的誓言无声
  11. 腾讯面试题, 2020年,让我们愉快的赛一次马!
  12. Java —— 日期时间 API
  13. java课设的总结和体会,JAVA设计培训心得体会【两篇】
  14. java 控制台输入
  15. matlab upcoef,Matlab小波工具箱的使用2
  16. 【基础知识】~ LUT、CLB、面积/速度问题
  17. 近世代数 笔记与题型连载 第十一章(正规子群与商群)
  18. 什么是8口poe交换机?8口poe交换机有哪些特点?
  19. HTML5期末大作业:HTML+CSS+JS制作鲜花网站(学生网页设计作业源码)
  20. 一个 Python 的轻量级搜索工具 -- Whose

热门文章

  1. 汽车电子中的3225贴片晶振
  2. 批量插入图片并自动排版——《超级处理器》应用
  3. 视频转换器Prism Plus for mac轻松转换视频!
  4. wpe修改充值_【图片】【WPE修改】WPE修改金币、属性、全属性、魔方实测可用版!【古戈吧】_百度贴吧...
  5. Jave2-Java音频视频编码器
  6. 解决U盘1KB快捷方式病毒(暴风一号)方法
  7. 《FLUENT 14.0超级学习手册》——3.2 Gambit的应用
  8. 房地产“产权分割制”是什么大杀器?
  9. 注册表修改服务器连接数量,如何通过Win10注册表更改时间服务器参数值?
  10. DISCUZ!论坛管理员无法登录后台的各种解决方法总结