Linux|函数mmap()解决花屏问题

    科技2022-07-12  123

    嵌入式实验

    引语mmap函数介绍案例

    write()函数效率比较低,容易出现花屏的现象。为解决花屏问题,所以使用mmap() mmap()的作用:将Linux内核(驱动)程序中显存的地址直接映射到应用程序中,我们在应用程序中,可以直接通过映射后的地址来访问显存,提高显存的访问效率。而write()函数是一个个字节将应用程序的数据写到驱动程序的显存的,中间有一个系统调用的过程,效率低。

    引语

    记录学习路程,抛砖引玉。如有更好的算法或者出现错误,欢迎指点。

    mmap函数介绍

    #include <sys/mman.h>

    1.内存的映射函数 void *mmap(void addr, size_t length, int prot, int flags, int fd, off_t offset); 参数说明: void addr ---->NULL,系统自动选择映射的地址。 size_t length —>映射内存的大小:8004804 int prot ---->映射后的内存区的访问属性:PROT_READ、 PROT_WRITE int flags ----- MAP_SHARED映射后的内存区是多进程间共享的。 int fd -----要映射的设备,文件描述符。 off_t offset ------ 映射的偏移量,一般为0. 返回值: void * ----->映射到应用程序中的内存地址。

    2.解除内存映射的函数 int munmap(void *addr, size_t length);

    void addr ---- 映射到应用程序中的内存地址。 size_t length ---- 映射内存的大小:800480*4

    #include<sys/mman.h> lcd_base = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, fd_lcd, 0);

    案例

    图片和单色之间切换,并避免出现花屏问题 代码如下:

    #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<stdio.h> #include<sys/mman.h> int lcd_show_color(unsigned int color) { int fd_lcd; int lcd_buf[800*480];//显存。int -- 4B int x,y; int *lcd_base=NULL;//在应用程序中,显存的首地址 fd_lcd=open("/dev/fb0",O_RDWR); if(fd_lcd==-1) { perror("open lcd"); return -1; } printf("fd_lcd=%d\n",fd_lcd); lcd_base=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE, MAP_SHARED,fd_lcd,0); if(lcd_base==NULL) { printf("mmap error\n"); return -1; } for(x=0;x<800*480;x++) { *(lcd_base+x)=color; } munmap(lcd_base,800*480*4); close(fd_lcd); return 0; } int lcd_show_bmp(char *bmp_name) { int fd_lcd,fd_bmp; int lcd_buf[800*480]; char bmp_buf[800*480*3]; int i,x,y; int *lcd_base=NULL; fd_bmp=open(bmp_name,O_RDONLY); if(fd_bmp==-1) { perror("open bmp"); return -1; } lseek(fd_bmp,54,SEEK_SET); read(fd_bmp,bmp_buf,sizeof(bmp_buf)); close(fd_bmp); //图片上下翻转。 for(x=0;x<480;x++) { for(y=0;y<800;y++) { lcd_buf[x*800+y]=((0x00<<24)+ (bmp_buf[((480-x)*800+y)*3+1]<<8)+ (bmp_buf[((480-x)*800+y)*3+2]<<16)+ (bmp_buf[((480-x)*800+y)*3+0]<<0)); } } fd_lcd = open("/dev/fb0", O_RDWR); if(fd_lcd == -1) { perror("open lcd"); return -1; } printf("fd_lcd = %d\n", fd_lcd); lcd_base = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, fd_lcd, 0); if(lcd_base == NULL) { printf("mmap error\n"); return -1; } for(i=0;i<800*480;i++) *(lcd_base + i) = lcd_buf[i]; munmap(lcd_base, 800*480*4); close(fd_lcd); } int main(void) { int fd_lcd; int fd_bmp1=-1,fd_bmp2=-1; char *bmp1="./lx1.bmp",*bmp2="./lx2.bmp"; unsigned int cr,cg,cb; cr=0x00FF0000;cg=0x0000FF00;cb=0x000000FF;//红、绿、蓝 while(1) { lcd_show_color(cr); sleep(1); lcd_show_bmp(bmp2); sleep(1); lcd_show_color(cg); sleep(1); lcd_show_bmp(bmp1); sleep(1); lcd_show_color(cb); sleep(1); lcd_show_bmp(bmp2); sleep(1); } }
    Processed: 0.010, SQL: 8