mmap函数分析使用实例

版权声明:学习记录,积少成多 https://blog.csdn.net/changliang7731/article/details/53707156

mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中作用很大。
gcc man中的描述
mmap() creates a new mapping in the virtual address space of the call‐ing process. The starting address for the new mapping is specified in addr. The length argument specifies the length of the mapping.

If addr is NULL, then the kernel chooses the address at which to create the mapping; this is the most portable method of creating a new map‐ping. If addr is not NULL, then the kernel takes it as a hint about where to place the mapping; on Linux, the mapping will be created at a nearby page boundary. The address of the new mapping is returned as the result of the call.

The prot argument describes the desired memory protection of the map‐ping (and must not conflict with the open mode of the file).

The flags argument determines whether updates to the mapping are visi‐ble to other processes mapping the same region, and whether updates are carried through to the underlying file.

用户空间:
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
参数:
addr: 通常为0或者NULL
length:映射区的长度,如果不是一个页大小,按一个页算,一个页通常为4k
prot:期望的内存保护标志

PROT_EXEC Pages may be executed.
PROT_READ Pages may be read.
PROT_WRITE Pages may be written.
PROT_NONE Pages may not be accessed.

flags:指定映射对象的类型

MAP_SHARED :Share this mapping. Updates to the mapping are visible to other processes that map this file, and are carried through to the underlying file. The file may not actually be updated until msync(2) or munmap() is called.

MAP_PRIVATE:Create a private copy-on-write mapping. Updates to the map‐ping are not visible to other processes mapping the same file, and are not carried through to the underlying file.It is unspecified whether changes made to the file after the mmap() call are visible in the mapped region.
MAP_32BIT
MAP_ANON
MAP_ANONYMOUS
MAP_DENYWRITE
MAP_EXECUTABLE
MAP_FILE
MAP_FIXED
MAP_GROWSDOWN
etc
fd:文件指针
offset:偏移位置
int munmap(void *addr, size_t length);

内核空间中设备驱动程序中也有一个mmap:
static int mmap(struct file * file,struct vm_area_struct * vma)

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
当调试uboot时,可以通过md命令查看某些寄存器或者管脚的状态.
当挂载linux内核后,如果想要查看某些寄存器的值,我们可以通过mmap来实现.
用户空间调用mmap函数,内核空间在对应的设备驱动中实现相应的mmap函数.

扫描二维码关注公众号,回复: 3786763 查看本文章

int remap_pfn_range(struct vm_area_struct*vma, unsigned long addr, unsigned long pfn, unsignedlong size, pgprot_t prot)
vma:用户层使用的vma 虚拟的内存指针
addr:用户的起始地址
pfn:内核空间的物理地址所在页帧号。通过物理地址>>PAGE_SHIFT得到
size:待映射区域大小
prot:vma页保护标志
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1.控制led灯的亮暗
2.读取当前led 脚的输出状态的寄存器值
3.改变led的亮暗情况
4.再读取led脚的输出状态
5.比较读出的值和实际的led表现是否一致

通过查datasheet和线路图,我知道led的输出寄存器为0xE0200284(PA),我们知道内核中使用的都是虚拟地址.

用户空间想要读取 0xE0200284的值,可以通过mmap来实现.这样我们想要读某个寄存器的值,将是很方便的事情.

效果:

首先,最开始的时候led灯4个都是关闭的,此时输出 高电平.读出来的管脚是0x0f
然后,依次打开4个led灯,此时输出低电平.读出来的管脚是0x0

这是很有用的一个功能.

猜你喜欢

转载自blog.csdn.net/changliang7731/article/details/53707156