Nir*_*Nir 2 c memory-management
在CI中有一个函数foo(char*),它接受一个内存指针.在调用者中,我有两个不同的内存缓冲区,我需要连接,所以我可以传递一个指针foo().有没有办法让我这样做而不实际将一个缓冲区复制到另一个缓冲区的末尾而不改变foo()本身?即使两个缓冲区显示为foo()的一个虚拟连续缓冲区
出于性能原因,我需要这个.O(n)解决方案(其中n是缓冲区长度之一)对我的情况是不可接受的.此外,Linux特定的解决方案很好,如果它有帮助.
谢谢.尼尔
是的,有一种方法.
为缓冲区分配内存,使它们在内存中相邻.
例:
char* a = malloc(a_size + b_size);
char* b = a + a_size;
Run Code Online (Sandbox Code Playgroud)
这个问题似乎要问是否可以将两个缓冲区(A和B)的内容与以下约束连接起来:
鉴于这一切,我的答案是否定的:这是不可能的.
是的,OS内核可以使用CPU的MMU(内存管理单元,在具有一个内存的架构上)重新映射内核虚拟地址空间或用户虚拟地址空间中的内存.分配一个连续的虚拟地址空间块,然后通过修改虚拟地址空间块的页表条目以指向A和B的物理地址,将A和B重新映射到该缓冲区.
这不会更改A本身的虚拟地址(因为旧的虚拟地址仍然有效),但它确实要求您通过不同的虚拟地址访问它.这可能是个问题.
今天典型CPU架构上的这种重新映射的粒度基于页面大小,并且由于A和B不是页面对齐的,也不是页面大小的倍数,因此您将无法使它们完全对齐.这绝对是个问题.
重新映射N个字节需要为每M个字节修改至少一个页表条目,其中M是页面大小.这意味着重映射操作无论如何都具有O(n)的计算复杂度.其他操作(例如为页表分配更多物理页面,刷新高速缓存和TLB等)会产生额外的性能影响.
另外,我想知道这个问题的目标是否涉及DMA(直接内存访问).使用需要连续内存的旧设备执行DMA时,除非您拥有IOMMU,否则无需重新映射数量.一个可以进行分散 - 聚集DMA的现代设备首先不需要连续的缓冲区.