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);


目录
相关文章
|
1月前
|
安全 Linux iOS开发
Binary Ninja 5.1.8104 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
Binary Ninja 5.1.8104 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
259 53
Binary Ninja 5.1.8104 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
|
1月前
|
Linux API iOS开发
Binary Ninja 4.2.6455 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
Binary Ninja 4.2.6455 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
142 14
Binary Ninja 4.2.6455 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
|
5月前
|
存储 弹性计算 缓存
阿里云服务器ECS经济型、通用算力、计算型、通用和内存型选购指南及使用场景分析
本文详细解析阿里云ECS服务器的经济型、通用算力型、计算型、通用型和内存型实例的区别及适用场景,涵盖性能特点、配置比例与实际应用,助你根据业务需求精准选型,提升资源利用率并降低成本。
398 3
|
30天前
|
设计模式 缓存 Java
【JUC】(4)从JMM内存模型的角度来分析CAS并发性问题
本篇文章将从JMM内存模型的角度来分析CAS并发性问题; 内容包含:介绍JMM、CAS、balking犹豫模式、二次检查锁、指令重排问题
72 1
|
2月前
|
缓存 监控 Linux
Linux内存问题排查命令详解
Linux服务器卡顿?可能是内存问题。掌握free、vmstat、sar三大命令,快速排查内存使用情况。free查看实时内存,vmstat诊断系统整体性能瓶颈,sar实现长期监控,三者结合,高效定位并解决内存问题。
141 0
Linux内存问题排查命令详解
|
2月前
|
数据管理 Linux iOS开发
Splunk Enterprise 9.4.5 (macOS, Linux, Windows) - 机器数据管理和分析
Splunk Enterprise 9.4.5 (macOS, Linux, Windows) - 机器数据管理和分析
91 0
|
3月前
|
缓存 监控 Linux
CentOS系统如何查看当前内存容量。
以上方法都不需要特殊软件或者复杂配置即可执行,在CentOS或其他Linux发行版中都适合运行,并且它们各自透露出不同角度对待问题解答方式:从简单快速到深入详尽;从用户态到核心态;从操作层数到硬件层数;满足不同用户需求与偏好。
313 8
|
4月前
|
存储 人工智能 自然语言处理
AI代理内存消耗过大?9种优化策略对比分析
在AI代理系统中,多代理协作虽能提升整体准确性,但真正决定性能的关键因素之一是**内存管理**。随着对话深度和长度的增加,内存消耗呈指数级增长,主要源于历史上下文、工具调用记录、数据库查询结果等组件的持续积累。本文深入探讨了从基础到高级的九种内存优化技术,涵盖顺序存储、滑动窗口、摘要型内存、基于检索的系统、内存增强变换器、分层优化、图形化记忆网络、压缩整合策略以及类操作系统内存管理。通过统一框架下的代码实现与性能评估,分析了每种技术的适用场景与局限性,为构建高效、可扩展的AI代理系统提供了系统性的优化路径和技术参考。
213 4
AI代理内存消耗过大?9种优化策略对比分析
|
4月前
|
存储 缓存 监控
手动清除Ubuntu系统中的内存缓存的步骤
此外,只有系统管理员或具有适当权限的用户才能执行这些命令,因为这涉及到系统级的操作。普通用户尝试执行这些操作会因权限不足而失败。
706 22
|
4月前
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
273 15