================================================
mmap ( 建立内存映射 )
- 头文件
#include <unistd.h>
#include <sys/mman.h> - 定义函数
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offsize);
- 函数说明
mmap()用来将某个文件内容映射到内存中, 对该内存区域的存取即是直接对该文件内容的读写. - 参数start 指向欲对应的内存起始地址, 通常设为 NULL, 代表让系统自动选定地址, 对应成功后该地址会返回.
- 参数length 代表将文件中多大的部分对应到内存.
- 参数 prot 代表映射区域的保护方式有下列组合
PROT_EXEC 映射区域可被执行
PROT_READ 映射区域可被读取
PROT_WRITE 映射区域可被写入
PROT_NONE 映射区域不能存取 - 参数 flags 会影响映射区域的各种特性
MAP_FIXED 如果参数 start 所指的地址无法成功建立映射时, 则放弃映射, 不对地址做修正.通常不鼓励用此旗标.
MAP_SHARED 对应射区域的写入数据会复制回文件内, 而且允许其他映射该文件的进程共享.
MAP_PRIVATE 对应射区域的写入操作会产生一个映射文件的复制, 即私人的"写入时复制" (copyon write)对此区域作的任何修改都不会写回原来的文件内容.
MAP_ANONYMOUS 建立匿名映射. 此时会忽略参数 fd, 不涉及文件, 而且映射区域无法和其他进程共享.
MAP_DENYWRITE 只允许对应射区域的写入操作, 其他对文件直接写入的操作将会被拒绝.
MAP_LOCKED 将映射区域锁定住, 这表示该区域不会被置换(swap).在调用 mmap()时必须要指定 MAP_SHARED 或 MAP_PRIVATE. - 参数 fd 为 open()返回的文件描述词,代表欲映射到内存的文件. 参数offset为文件映射的偏移量, 通常设置为0, 代表从文件最前方开始对应, offset必须是分页大小的整数倍.
- 返回值
若映射成功则返回映射区的内存起始地址, 否则返回MAP_FAILED(-1), 错误原因存于 errno 中.错误代码 EBADF 参数 fd 不是有效的文件描述词
================================================
munmap ( 解除内存映射 )
- 头文件
#include <unistd.h>
#include <sys/mman.h> - 定义函数
int munmap(void *start, size_t length);
- 函数说明
munmap()用来取消参数 start 所指的映射内存起始地址, 参数 length 则是欲取消的内存大小. 当进程结束或利用 exec 相关函数来执行其他程序时, 映射内存会自动解除, 但关闭对应的文件描述词时不会解除映射. - 返回值
如果解除映射成功则返回 0, 否则返回-1, 错误原因存于 errno 中错误代码 EINVAL参数 start 或 length 不合法.
demo:
/********************************************************************
> File Name: 6.LCD图片.c
> Author: xiening
> Mail: [email protected]
> Created Time: 2019年11月21日 星期四 16时13分45秒
*******************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
int main(int argc, char const *argv[])
{
//打开文件
FILE *fp = fopen("./image.bmp", "r+");
//读image.bmp
fseek(fp, 54, SEEK_SET);
char buf[800*480*3];
int ret = fread(buf, 3, 800*480, fp);
if(800*480 != ret)
{
perror("fread error\n");
return -1;
}
//关闭文件
fclose(fp);
//打开文件:
FILE *fp1 = fopen("/dev/fb0", "r+");
int fd = fileno(fp1);
//内存映射:
unsigned *buf1 = mmap(NULL, 800*480*4,
PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0);
//写入LCD:
for(int i=0; i<480; i++)
{
for(int j=0; j<800; j++)
{
buf1[800*480-1-(i*800+799-j)] = buf[(i*800+j)*3]
| buf[(i*800+j)*3+1] << 8
| buf[(i*800+j)*3+2] << 16;
}
}
//解除映射
fclose(fp1);
munmap(buf1, 800*480);
close(fd);
return 0 ;
}