一个问题,关于kmalloc分配的内存和编译器自动分配的内存的问题(堆和栈)

时间:2021-07-21 02:23:56
我们知道,kmalloc分配的内存在堆中,编译器给变量自动分配的内存在栈中,但是我现在就出现了一个问题
kmalloc分配的内存可以用来进行dma传输,而在栈中的变量就不能用进行dma传输,这是为什么?
我用的是网卡的dma,只要写进变量的首地址(都已经转换成物理地址)以及长度,它就能够进行传输,但是变量没用kmalloc分配内存,就不能用它的地址进行传输!
是否因为堆和栈转换成物理地址是不连续的?还是其他原因?

12 个解决方案

#1


栈空间在退出函数的时候就回收了,而堆则不会。

#2


不是因为收回的原因 因为我试过在函数里延迟,等待dma完成,结果传出去的数据还是错的

#3


查一下是不是有字节对齐的问题。

#4


回楼上的 也不是字节对齐问题,是不是dma传输都有地址限制的?

#5


关注。

#6


你用的是什么CPU?

#7


at91rm9200

#8


用来做DMA的内存不能Cache, 编译器给变量自动分配的内存会使用cache。 如果CPU没有MMIO的话,申请到的内存一般都是连续的

#9


对于DMA内存,一般需要分配前16M的物理内存,而且要关掉CACHE。Linux的kmalloc可以分配两种内存,DMA内存与非DMA内存,所以为DMA分配的内存都要用GFP_DMA标志。在栈中,分配的内存应该不是DMA内存:1、可能DMA没有从前16M物理内存中分配(你的芯片应该没有这限制)。2、可能没有关掉CACHE(芯片如果支持MMU,一般就支持CACHE)。所以会出现这种问题。

#10


好像,16MB限制只有ISA的设备才有
如果是PCI的可以到4GB

#11


无论堆还是栈,使用的都是虚拟内存
但malloc申请到的虚拟内存和物理内存是一对一的映射关系的,即虚拟内存在物理上是连续的
而在栈中分配时,所分配的虚拟内存在逻辑上是连续的,但物理上可能不连续,可能会导致问题

#12


同意楼上的观点,kmalloc()返回的是一个内核逻辑地址,逻辑地址与实际的物理内存只是有一个简单的偏移,虽说逻辑地址也是虚拟地址,但是它与物理地址是一一对应而且连续的,而堆栈地址在逻辑上是连续的,在物理上并没有一一对应而且线性的关系,所以不能用作DMA传输

#1


栈空间在退出函数的时候就回收了,而堆则不会。

#2


不是因为收回的原因 因为我试过在函数里延迟,等待dma完成,结果传出去的数据还是错的

#3


查一下是不是有字节对齐的问题。

#4


回楼上的 也不是字节对齐问题,是不是dma传输都有地址限制的?

#5


关注。

#6


你用的是什么CPU?

#7


at91rm9200

#8


用来做DMA的内存不能Cache, 编译器给变量自动分配的内存会使用cache。 如果CPU没有MMIO的话,申请到的内存一般都是连续的

#9


对于DMA内存,一般需要分配前16M的物理内存,而且要关掉CACHE。Linux的kmalloc可以分配两种内存,DMA内存与非DMA内存,所以为DMA分配的内存都要用GFP_DMA标志。在栈中,分配的内存应该不是DMA内存:1、可能DMA没有从前16M物理内存中分配(你的芯片应该没有这限制)。2、可能没有关掉CACHE(芯片如果支持MMU,一般就支持CACHE)。所以会出现这种问题。

#10


好像,16MB限制只有ISA的设备才有
如果是PCI的可以到4GB

#11


无论堆还是栈,使用的都是虚拟内存
但malloc申请到的虚拟内存和物理内存是一对一的映射关系的,即虚拟内存在物理上是连续的
而在栈中分配时,所分配的虚拟内存在逻辑上是连续的,但物理上可能不连续,可能会导致问题

#12


同意楼上的观点,kmalloc()返回的是一个内核逻辑地址,逻辑地址与实际的物理内存只是有一个简单的偏移,虽说逻辑地址也是虚拟地址,但是它与物理地址是一一对应而且连续的,而堆栈地址在逻辑上是连续的,在物理上并没有一一对应而且线性的关系,所以不能用作DMA传输