C语言 NOTE16

================================================
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 ;
}

发布了52 篇原创文章 · 获赞 2 · 访问量 2018

猜你喜欢

转载自blog.csdn.net/weixin_42191545/article/details/103177501