Linux应用编程---mmap

是什么

二话不说,上来就问下那个man

NAME
       mmap, munmap - map or unmap files or devices into memory
SYNOPSIS
       #include <sys/mman.h>
       void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);
       int munmap(void *addr, size_t length);

mmap是用来映射一个文件或者设备到内存,这个内存当然指虚拟地址。
mmap是一个标准系统调用------>sys_mmap2
介绍下参数
addr:传入的虚拟地址,表示你想用的虚拟地址,可以为NULL,内核帮你挑一个虚拟地址,如果传入的虚拟地址冲突,内核会重新帮你选一个。
length: 你想映射地址的长度
prot参数描述映射所需的内存保护(并且一定不能与文件的打开模式冲突),可一个可组合,PROT_EXEC,PROT_READ,PROT_WRITE,PROT_NONE(page 不能被访问)。
flag:更新是是否对映射同一块区域的其他进程是否可见。参数较多,只介绍常用的2个
MAP_SHARED:共享这个映射更新时,其他进程可见,《注意》在调用msync(2)或munmap()之前,文件实际上可能不会被更新。
MAP_PRIVATE: Create a private copy-on-write mapping.映射更新对其他进程不可见,且不会传递到底层文件。
fd:想要映射的文件或者设备
offset:打开文件时的偏移,必须页对齐,multiple of the
page size as returned by sysconf(_SC_PAGE_SIZE),假如不对齐,底层返回-EINVAL,错误码
返回值:On success, mmap() returns a pointer to the mapped area. On error, the value MAP_FAILED (that is, (void *) -1) is returned, and
errno is set appropriately. On success, munmap() returns 0, on failure -1, and errno is set (probably to EINVAL).
注意 mmap失败返回MAP_FAILED(-1),errno错误码
munmap失败返回-1,

munmap:
1.进程终止时该区域自动取消映射,close fd不会取消当前的映射

怎么用

用途

1.映射文件,可以直接修改文件内容或者修改文件某一块内容,而不必打开文件,加载全部内容。
2.映射物理内容,app可直接操作物理地址,将寄存器映射到app,使用结构体可直接操作底层寄存器。

常用方法:

fd = open("/dev/mem", O_RDWR | O_SYNC);
addr = mmap(NULL, _SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PHY_ADDR);
munmap(addr , PHY_ADDR);
PHY_ADDR就是你想要映射的物理地址。记得页对齐

以share方式mmap,fsync(fd)以及msync都会立即更新到文件中ctrl+c退出线程也会更新进文件。这里需要注意知识点
ummap,后系统不会吧数据同步进文件 不会,不会
fsync(fd)以及msync或者Ctrl+c线程退出才会更新到文件

切记ummap不会写进文件可以手写代码然后断电验证,虽然man里说的 “或munmap()之前,文件实际上可能不会被更新“

msync用法

NAME
       msync - synchronize a file with a memory map
SYNOPSIS
       #include <sys/mman.h>
       int msync(void *addr, size_t length, int flags);
       
       RETURN VALUE
       On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.

addr:申请的虚拟地址,必须页对齐。
flags:MS_ASYNC /MS_SYNC(这俩互斥),MS_INVALIDATE
MS_ASYNC:与内核高速缓存同步后立即返回,高速缓存以磁盘的同步在pdflush线程完成异步同步
MS_SYNC:等到写入磁盘完成后返回
MS_INVALIDATE:试映射的缓存数据无效,

有些时候我们映射外设的物理地址使用msync MS_SYNC有时候会报错
msync -22 Invalid argument,很有可能是sync中mem没有fops导致的
没有设置fsync文件操作处理程序
if (!file->f_op->fsync)
return -EINVAL;
这个时候我们采用另一种方式来解决缓存问题
即打开设备文件的时候采用无缓存标志,这样就不需要同步了
fid= open("/dev/XXX", O_RDWR | O_SYNC);
fd = open("/dev/mem", O_RDWR | O_SYNC);
或者采用MS_ASYNC进行同步

Guess you like

Origin blog.csdn.net/weixin_41884251/article/details/111318632