我写了一个内核程序用于内存读/写操作。
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/init.h>
#include<linux/io.h>
static uint32_t *mem_alloc(void)
{
uint32_t *base, *mem;
base=kmalloc(5*sizeof(uint32_t),GFP_KERNEL);
mem=ioremap(base,5*sizeof(uint32_t));
return(mem);
}
static void mem_write(uint32_t *memory)
{
uint32_t *mem1;
mem1=memory;
int i;
for(i=0;i<5;i++)
{
*mem1=0x1010F0F0;
mem1++;
}
}
static int __init insert(void)
{
uint32_t *memory;
memory=mem_alloc();
mem_write(memory);
return 0;
}
static void __exit remove(uint32_t *memory)
{
kfree(memory);
}
在此程序中,执行指令时发生总线错误
*mem1=0x1010F0F0;
ioremap() 用于将总线内存映射到 CPU 空间。
ioremap 执行特定于平台的操作序列以使总线内存 CPU 可通过 readb/readw/readl/writeb/writew/writel 函数和其他 MMIO 帮助程序访问。返回的地址不保证可直接用作虚拟地址。
kmalloc 在物理内存中的连续内存位置分配内存,并返回其虚拟地址指针。
IOREMAP 在输入中需要物理地址,但您将虚拟地址作为物理地址提供给 ioremap。该虚拟地址值可能与任何总线的物理地址值相同,并且它将物理总线空间映射到虚拟(我们必须使用readb/readw/readl/writeb/writew/writel访问设备寄存器),因为它给出了错误。
发现的ioremap参考:
void* ioremap (无符号长phys_addr,
无符号长尺寸
)将 I/O 内存重新映射到内核地址空间。
参数: phys_addr物理地址范围的
开头 物理地址范围的大小大小返回: 映射范围的虚拟起始地址 这里没有进行真正的映射。仅返回虚拟地址。
看起来它将硬件设备地址映射到虚拟内存,而不是从实际内存分配的内存块。