Linux kernel 将物理设备映射到用户空间中的指针

Linux kernel 将物理设备映射到用户空间中的指针,linux-kernel,device,linux-device-driver,embedded-linux,mmap,Linux Kernel,Device,Linux Device Driver,Embedded Linux,Mmap,我们有一个嵌入式系统,其中连接了内存映射设备,ARM CPU运行Linux。该设备位于地址0x40400000,占用1兆字节(其中大部分没有实际内存支持,但地址空间仍映射到该设备)。我们目前没有此设备的设备驱动程序 在设备中,地址0x404f0704处有一个特殊的只读寄存器(称为CID)。此寄存器包含值CID=0x404。我试图从ARM上运行的程序中读取此寄存器 搜索网络时,我了解了mmap()函数,该函数假定允许我从用户空间访问物理地址。因此,为了遵循我发现的几个示例,我编写了以下测试: #

我们有一个嵌入式系统,其中连接了内存映射设备,ARM CPU运行Linux。该设备位于地址
0x40400000
,占用1兆字节(其中大部分没有实际内存支持,但地址空间仍映射到该设备)。我们目前没有此设备的设备驱动程序

在设备中,地址
0x404f0704
处有一个特殊的只读寄存器(称为CID)。此寄存器包含值
CID=0x404
。我试图从ARM上运行的程序中读取此寄存器

搜索网络时,我了解了
mmap()
函数,该函数假定允许我从用户空间访问物理地址。因此,为了遵循我发现的几个示例,我编写了以下测试:


#包括

#includeMmap是通常用于虚拟地址的函数。当您调用
mmap(…MAP\u ANONYMOUS)
(或
/dev/zero
文件的
mmap
)时,它将为您提供一些新的虚拟内存,其中包含零。返回的地址将是虚拟内存的地址

您可以mmap一些文件(不使用MAP_ANONYMOUS),然后mmap将文件内容映射到某个虚拟内存范围

该设备位于地址0x40400000

设备MMIO位于物理内存中;任何进程都可以使用虚拟地址0x40400000;但它们将被MMU(内存管理单元)映射(转换)到某个空闲物理页。你不能仅仅要求操作系统提供一些虚拟内存,然后期望它能被移动到设备范围(它将是地狱的变体)

但是有一个特殊的设备,/dev/mem,它可以用作包含所有物理内存的文件。 当你
mmap
s/dev/mem时,你实际上是在要求操作系统创建一些虚拟内存到所要求的物理范围的新映射

在调用mmap时:

 mapped_base = mmap(0, MAP_SIZE, PROT_READ|PROT_WRITE, 
   MAP_SHARED, memfd, dev_base & ~MAP_MASK);
您要求将物理内存范围
[0x40400000..0x4050000-1]
(1兆字节;不包括字节0x40500000)映射到某个兆字节的虚拟内存中(其起始地址由mmap返回)

pu   = 0x40400000
pcid = 0x404f0704
CID  = 0
CID  = 404
 mapped_base = mmap(0, MAP_SIZE, PROT_READ|PROT_WRITE, 
   MAP_SHARED, memfd, dev_base & ~MAP_MASK);