Linux编程之mmap示例

Linux下的文件读写通常涉及三次数据拷贝。mmap提供了一种优化方式,允许直接在用户空间读写page cache,减少了拷贝次数。通过mmap映射文件的页缓存,读写操作直接作用于文件,但需注意同步到磁盘的时机:msync、munmap、进程退出或系统关机。本文包含mmap示例和理论解析。
摘要由CSDN通过智能技术生成

一、问题背景

Linux下,针对文件读写操作,一般有三个步骤:
1)把文件内容读入到内存中;调用read(系统调用),从内核态读取文件内容到虚拟内存;
2)修改内存中的内容;在用户空间修改内存中的信息;
3)把内存的数据写入到文件中;调用write(系统调用),从用户态将修改后的内容写入到文件;
过程如下图所示:(本文只讨论mmap,关于page cache,请查看:https://www.cnblogs.com/ronnieyuan/p/12377059.html

显然一次文件的修改操作,我们对文件内容拷贝了两次;

如何优化上述的文件读写操作?如果可以直接在用户空间读写page cache,那么就不需要将文件数据拷贝到用户空间缓存区这个动作了,mmap即可完成;

使用mmap系统调用可以将用户空间的虚拟内存地址与文件进行映射绑定,对映射或的虚拟内存地址进行读写操作,就如同对文件进行读写操作一样。原理图如下所示:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在嵌入式Linux下进行LCD编程,需要使用Linux内核提供的framebuffer(FB)驱动程序来操作显示屏。FB驱动程序提供了一个虚拟显存,开发人员可以通过将数据写入虚拟显存来控制显示屏。对于800*480bmp图片的显示,可以将其存储在内存中,然后将数据写入虚拟显存,在显示屏上显示。 要让图片在开发板上动态移动,可以使用双缓冲技术。使用双缓冲技术,可以在一个缓冲区中绘制图形,同时在另一个缓冲区中显示图形。当需要更新显示时,可以交换缓冲区,将绘制好的图形显示在显示屏上。 下面是一个简单的示例代码,可以在800*480分辨率的LCD上显示一张图片,并让它在屏幕上水平移动: ``` #include <fcntl.h> #include <linux/fb.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv) { int fbfd = 0; struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; long int screensize = 0; char *fbp = 0; int x = 0, y = 0; long int location = 0; // 打开framebuffer设备 fbfd = open("/dev/fb0", O_RDWR); if (fbfd == -1) { printf("Error: cannot open framebuffer device.\n"); exit(1); } // 获取可变屏幕信息和固定屏幕信息 if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) { printf("Error: cannot get framebuffer variable information.\n"); exit(1); } if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) { printf("Error: cannot get framebuffer fixed information.\n"); exit(1); } // 计算屏幕大小(字节) screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; // 映射framebuffer到内存 fbp = (char *) mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); if ((int) fbp == -1) { printf("Error: failed to map framebuffer device to memory.\n"); exit(1); } // 读取图片数据 FILE *fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Error: cannot open BMP file.\n"); exit(1); } fseek(fp, 54, SEEK_SET); char *bmp_data = (char *) malloc(screensize); fread(bmp_data, screensize, 1, fp); fclose(fp); // 双缓冲技术 char *buffer = (char *) malloc(screensize); memcpy(buffer, fbp, screensize); // 移动图片 int dx = 1; while (1) { for (y = 0; y < vinfo.yres; y++) { for (x = 0; x < vinfo.xres; x++) { location = (x + vinfo.xoffset) * (vinfo.bits_per_pixel / 8) + (y + vinfo.yoffset) * finfo.line_length; if (location >= 0 && location < screensize) { *(buffer + location) = *(fbp + location + dx * (vinfo.bits_per_pixel / 8)); } } } memcpy(fbp, buffer, screensize); dx = dx + 1; if (dx >= vinfo.xres) { dx = 0; } } // 解除内存映射 munmap(fbp, screensize); // 关闭framebuffer设备 close(fbfd); return 0; } ``` 这段代码使用了mmap函数将framebuffer设备映射到内存中,然后读取了一张BMP图片,将图片数据写入虚拟显存。使用双缓冲技术,将虚拟显存中的数据复制到另一个缓冲区中,然后在屏幕上显示。在每个时刻,将缓冲区中的数据向右移动一个像素,然后再复制到虚拟显存中,实现了动态移动的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值