我为内存读/写操作编写了一个内核程序。
#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;
答案 0 :(得分:3)
ioremap()用于将总线内存映射到CPU空间。
ioremap 执行特定于平台的操作序列以生成总线内存CPU 可通过readb / readw / readl / writeb / writew / writel函数和其他mmio助手访问。 不保证返回的地址可以直接用作虚拟地址。
kmalloc 在物理内存中的连续内存位置分配内存并返回它的虚拟地址指针。
ioremap需要输入中的物理地址,,但您将虚拟地址作为物理地址提供给ioremap 。该虚拟地址值可能与物理地址值相同任何总线,它将物理总线空间映射到虚拟(我们必须使用readb / readw / readl / writeb / writew / writel访问设备寄存器),因为它给出了错误。
答案 1 :(得分:0)
我发现这是ioremap的参考:
void * ioremap(unsigned long phys_addr,
无符号长尺寸 )将I / O内存重新映射到内核地址空间。
参数: phys_addr物理地址范围的开始
物理地址范围的大小返回: 映射范围的虚拟起始地址 这里没有真正的映射。仅返回虚拟地址。
看起来它将硬件设备地址映射到虚拟内存,而不是从真实内存分配的内存块。