linux系统中内存分配常见函数的分析与实现

简介: linux系统中内存分配常见函数的分析与实现

2a528dd7c0ee60b6b8fe52883ae208a0.png


第一:linux系统中内存分配关注问题


    在编写Linux驱动过程中,不可避免涉及外设操作,而外设地址空间与DDR地址空间一般不连续,在linux上电时,并不会为外设地址空间建立页表,又因为linux访问内存使用的都是虚拟地址,因此如果想访问外设的寄存器(一般包括数据寄存器、控制寄存器与状态寄存器),需要在驱动初始化中将外设所处的物理地址映射为虚拟地址,linux为应对该问题提供了较多接口,包括:ioremap/ioremap_wc/devm_ioremap/devm_ioremap_resource等,以应对不同的场景需求,本文即阐述这些接口的使用,以及需要注意的区别。


第二:场景的应用背景


  在系统运行时,外设IO资源的物理地址是已知的,由硬件的设计决定(参考SOC的datesheet,一般会有memorymap)。驱动程序不能通过物理地址访问IO资源,必须将其映射到内核态的虚拟地址空

间(通过页表)[1],然后根据映射所得到的内核虚拟地址范围,通过线性偏移(virt_addr = virt_base + phy_addr - phy_base)访问这些IO内存资源。

代码路径:arch/arm/include/asm/io.h
/*                                                                                                  
349  * ioremap() and friends.                                                                           
350  *                                                                                                  
351  * ioremap() takes a resource address, and size.  Due to the ARM memory                             
352  * types, it is important to use the correct ioremap() function as each                             
353  * mapping has specific properties.                                                                 
354  *                                                                                                  
355  * Function             Memory type     Cacheability    Cache hint                                  
356  * ioremap()            Device          n/a             n/a                                         
357  * ioremap_nocache()    Device          n/a             n/a                                         
358  * ioremap_cache()      Normal          Writeback       Read allocate                               
359  * ioremap_wc()         Normal          Non-cacheable   n/a                                         
360  * ioremap_wt()         Normal          Non-cacheable   n/a                                         
361  *                                                                                                  
362  * All device mappings have the following properties:                                               
363  * - no access speculation                                                                          
364  * - no repetition (eg, on return from an exception)                                                
365  * - number, order and size of accesses are maintained                                              
366  * - unaligned accesses are "unpredictable"                                                         
367  * - writes may be delayed before they hit the endpoint device                                      
368  *                                                                                                  
369  * ioremap_nocache() is the same as ioremap() as there are too many device                          
370  * drivers using this for device registers, and documentation which tells                           
371  * people to use it for such for this to be any different.  This is not a  
372  * safe fallback for memory-like mappings, or memory regions where the                              
373  * compiler may generate unaligned accesses - eg, via inlining its own                              
374  * memcpy.                                                                                          
375  *                                                                                                  
376  * All normal memory mappings have the following properties:                                        
377  * - reads can be repeated with no side effects                                                     
378  * - repeated reads return the last value written                                                   
379  * - reads can fetch additional locations without side effects                                      
380  * - writes can be repeated (in certain cases) with no side effects                                 
381  * - writes can be merged before accessing the target                                               
382  * - unaligned accesses can be supported                                                            
383  * - ordering is not guaranteed without explicit dependencies or barrier                            
384  *   instructions                                                                                   
385  * - writes may be delayed before they hit the endpoint memory                                      
386  *                                                                                                  
387  * The cache hint is only a performance hint: CPUs may alias these hints.                           
388  * Eg, a CPU not implementing read allocate but implementing write allocate                         
389  * will provide a write allocate mapping instead.                                                   
390  */


ioremap函数组共有五个接口,根据函数实现可以分为三类:

ioremap & ioremap_nocache实现相同,使用场景为映射device memory类型内存;

ioremap_cached,使用场景为映射normal memory类型内存,且映射后的虚拟内存支持cache;

ioremap_wc & ioremap_wt实现相同,使用场景为映射normal memory类型内训,且映射后的虚拟内存不支持cache。


第三:何为memory type?


    内存类型(memory type)分为设备(device)类型与一般(normal)类型。


第四:ioremap & ioremap_nocache


代码路径:arch/arm/include/asm/io.h
void __iomem *ioremap(resource_size_t res_cookie, size_t size);
#define ioremap ioremap                                                                     #define ioremap_nocache ioremap


 ioremap用来映射memory type为device memory的设备,同时不使用cache(device memory本身就没有cacheable这个属性),即CPU的读写操作直接操作设备内存。ioremap_nocache的实现与ioremap完全相同,保留该符号是因为向后兼容使用ioremap_nocache接口的驱动程序。

   API接口中的res_cookie参数是需要映射的物理地址,size参数是需要映射的内存大小,单位是Byte。不需要考虑物理地址的页对齐问题,底层通过PAGE_ALIGN接口完成了页对齐。


第五:ioremap_cached


/*                                                                                                  
* Do not use ioremap_cached in new code. Provided for the benefit of                               
* the pxa2xx-flash MTD driver only.                                                                
 */                                                                                                 
void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size);


ioremap_cached用来映射memory type为normal memory的设备,同时使用cache,这会提高内存的访问速度,提高系统的性能。


第六:ioremap_wc & ioremap_wt


void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size);                                  
#define ioremap_wc ioremap_wc                                                                       
#define ioremap_wt ioremap_wc


ioremap_wc用来映射memory type为normal memory的设备,同时不使用cache。


第七:解映射API


代码路径:arch/arm/include/asm/io.h
void iounmap(volatile void __iomem *iomem_cookie);


不论采用以上哪种映射方式,解映射为统一接口,其中iomem_cookie参数为映射后的虚拟地址。


第八:IO资源读写过程


我们已经知道如何映射和解映射虚拟内存,内存映射是为了访问,理论上这时候可以像读写RAM那样直接通过虚拟地址指针读写IO内存资源,但是为了保证驱动程序跨平台的可移植性【这一点还不太理解,直接指针操作怎么影响的移植性,望大家指教】,我们应该采用linux中特定的接口函数来访问IO内存[1]。常用接口如下:

代码路径:arch/arm/include/asm/io.h
299 #define readb(c)                ({ u8  __v = readb_relaxed(c); __iormb(); __v; })                   
300 #define readw(c)                ({ u16 __v = readw_relaxed(c); __iormb(); __v; })                   
301 #define readl(c)                ({ u32 __v = readl_relaxed(c); __iormb(); __v; })                   
303 #define writeb(v,c)             ({ __iowmb(); writeb_relaxed(v,c); })                               
304 #define writew(v,c)             ({ __iowmb(); writew_relaxed(v,c); })                               
305 #define writel(v,c)             ({ __iowmb(); writel_relaxed(v,c); })   
316 static inline void memset_io(volatile void __iomem *dst, unsigned c,                                size_t count);
324 static inline void memcpy_fromio(void *to, const volatile void __iomem *from,                         size_t count);
332 static inline void memcpy_toio(volatile void __iomem *to, const void *from,                           size_t count);


目录
相关文章
|
3天前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
17 3
|
3天前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
15 2
|
3天前
|
安全 网络协议 Linux
本文详细介绍了 Linux 系统中 ping 命令的使用方法和技巧,涵盖基本用法、高级用法、实际应用案例及注意事项。
本文详细介绍了 Linux 系统中 ping 命令的使用方法和技巧,涵盖基本用法、高级用法、实际应用案例及注意事项。通过掌握 ping 命令,读者可以轻松测试网络连通性、诊断网络问题并提升网络管理能力。
18 3
|
6天前
|
安全 Linux 数据安全/隐私保护
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。本文介绍了使用 `ls -l` 和 `stat` 命令查找文件所有者的基本方法,以及通过文件路径、通配符和结合其他命令的高级技巧。还提供了实际案例分析和注意事项,帮助读者更好地掌握这一操作。
23 6
|
6天前
|
Linux
在 Linux 系统中,`find` 命令是一个强大的文件查找工具
在 Linux 系统中,`find` 命令是一个强大的文件查找工具。本文详细介绍了 `find` 命令的基本语法、常用选项和具体应用示例,帮助用户快速掌握如何根据文件名、类型、大小、修改时间等条件查找文件,并展示了如何结合逻辑运算符、正则表达式和排除特定目录等高级用法。
30 6
|
7天前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
7天前
|
机器学习/深度学习 自然语言处理 Linux
Linux 中的机器学习:Whisper——自动语音识别系统
本文介绍了先进的自动语音识别系统 Whisper 在 Linux 环境中的应用。Whisper 基于深度学习和神经网络技术,支持多语言识别,具有高准确性和实时处理能力。文章详细讲解了在 Linux 中安装、配置和使用 Whisper 的步骤,以及其在语音助手、语音识别软件等领域的应用场景。
29 5
|
7天前
|
缓存 运维 监控
【运维必备知识】Linux系统平均负载与top、uptime命令详解
系统平均负载是衡量Linux服务器性能的关键指标之一。通过使用 `top`和 `uptime`命令,可以实时监控系统的负载情况,帮助运维人员及时发现并解决潜在问题。理解这些工具的输出和意义是确保系统稳定运行的基础。希望本文对Linux系统平均负载及相关命令的详细解析能帮助您更好地进行系统运维和性能优化。
24 3
|
10天前
|
算法 Linux 开发者
深入探究Linux内核中的内存管理机制
本文旨在对Linux操作系统的内存管理机制进行深入分析,探讨其如何通过高效的内存分配和回收策略来优化系统性能。文章将详细介绍Linux内核中内存管理的关键技术点,包括物理内存与虚拟内存的映射、页面置换算法、以及内存碎片的处理方法等。通过对这些技术点的解析,本文旨在为读者提供一个清晰的Linux内存管理框架,帮助理解其在现代计算环境中的重要性和应用。
|
7天前
|
监控 网络协议 算法
Linux内核优化:提升系统性能与稳定性的策略####
本文深入探讨了Linux操作系统内核的优化策略,旨在通过一系列技术手段和最佳实践,显著提升系统的性能、响应速度及稳定性。文章首先概述了Linux内核的核心组件及其在系统中的作用,随后详细阐述了内存管理、进程调度、文件系统优化、网络栈调整及并发控制等关键领域的优化方法。通过实际案例分析,展示了这些优化措施如何有效减少延迟、提高吞吐量,并增强系统的整体健壮性。最终,文章强调了持续监控、定期更新及合理配置对于维持Linux系统长期高效运行的重要性。 ####