Linux下读取framebuffer(/dev/fb0)出来的数据全部是0,为啥会这样
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux下读取framebuffer(/dev/fb0)出来的数据全部是0,为啥会这样相关的知识,希望对你有一定的参考价值。
如题啊,我在linux下用C写读取framebuffer的代码,结果读取出来的数据全部是0,我以为是代码写错了,然后直接用命令 cat /dev/fb0 > fbfile来获得fb0,在用编辑器打开文件也是全都是0,这是为什么呢,但是fix_info和variable_info读取的是对的,但为什么读出来的图像全是0呢,不解,后来我在我的安卓手机上用同样的代码来读取/dev/graphics/fb0,其中一个手机读取的数据是对的,没有问题,而另一个手机读到的也全是0,着实很让我头痛。不解,求大神解释一下。在线等......
参考技术A 看看有没有其他的fb设备如fb1追问没有,我已经看过来,没有其他的fb,为什么会这样呢
追答你不会是用android的虚拟机吧 我记得就是有这种现象的 以前我研究过多种android下截屏的方式 现在暂时找不到那篇文档了
其实你不一定要手工读fb的 我最后用了连接adb server的方法 直接发送framebuffer:命令就得到了framebuffer的所有数据
你可以参考下android的源代码 /system/core/adb/framebuffer_service.c
没有用到虚拟机,我直接用cat或者dd命令取到的fb数据都是空的,16进制编辑器打开全是0,有一个手机是正确的,但是我在电脑上的linux就不行,发行版是mint16,另一个手机也不行,手机型号是google N4
Linux framebuffer显示bmp图片
本文转载自:http://blog.csdn.net/luxiaoxun/article/details/7622988
framebuffer简介
帧缓冲(framebuffer)是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。framebuffer是LCD对应的一中HAL(硬件抽象层),提供抽象的,统一的接口操作,用户不必关心硬件层是怎么实施的。这些都是由Framebuffer设备驱动来完成的。
帧缓冲设备对应的设备文件为/dev/fb*,如果系统有多个显示卡,Linux下还可支持多个帧缓冲设备,最多可达32个,分别为/dev/fb0到 /dev/fb31,而/dev/fb则为当前缺省的帧缓冲设备,通常指向/dev/fb0,在嵌入式系统中支持一个显示设备就够了。帧缓冲设备为标准字符设备,主设备号为29,次设备号则从0到31。分别对应/dev/fb0-/dev/fb31。
通过/dev/fb,应用程序的操作主要有这几种:
1. 读/写(read/write)/dev/fb:相当于读/写屏幕缓冲区。
2. 映射(map)操作:由于Linux工作在保护模式,每个应用程序都有自己的虚拟地址空间,在应用程序中是不能直接访问物理缓冲区地址的。而帧缓冲设备可以通过mmap()映射操作将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址上,然后用户就可以通过读写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图了。
3. I/O控制:对于帧缓冲设备,对设备文件的ioctl操作可读取/设置显示设备及屏幕的参数,如分辨率,屏幕大小等相关参数。ioctl的操作是由底层的驱动程序来完成的。
在应用程序中,操作/dev/fb的一般步骤如下:
1. 打开/dev/fb设备文件。
2. 用ioctl操作取得当前显示屏幕的参数,根据屏幕参数可计算屏幕缓冲区的大小。
3. 将屏幕缓冲区映射到用户空间。
4. 映射后即可直接读写屏幕缓冲区,进行绘图和图片显示。
framebuffer相关数据结构介绍
1. fb_info结构体:帧缓冲设备中最重要的数据结构体,包括了帧缓冲设备属性和操作的完整性属性。
2. fb_ops结构体:fb_info结构体的成员变量,fb_ops为指向底层操作的函数的指针。
3.fb_var_screen和fb_fix_screen结构体:fb_var_screen记录用户可以修改的显示控制器参数,fb_fix_screen记录用户不能修改的显示控制器参数。
以下代码使用framebuffer显示一张图片:
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <string.h>
- #include <linux/fb.h>
- #include <sys/mman.h>
- #include <sys/ioctl.h>
- #include <arpa/inet.h>
- //14byte文件头
- typedef struct
- {
- char cfType[2];//文件类型,"BM"(0x4D42)
- long cfSize;//文件大小(字节)
- long cfReserved;//保留,值为0
- long cfoffBits;//数据区相对于文件头的偏移量(字节)
- }__attribute__((packed)) BITMAPFILEHEADER;
- //__attribute__((packed))的作用是告诉编译器取消结构在编译过程中的优化对齐
- //40byte信息头
- typedef struct
- {
- char ciSize[4];//BITMAPFILEHEADER所占的字节数
- long ciWidth;//宽度
- long ciHeight;//高度
- char ciPlanes[2];//目标设备的位平面数,值为1
- int ciBitCount;//每个像素的位数
- char ciCompress[4];//压缩说明
- char ciSizeImage[4];//用字节表示的图像大小,该数据必须是4的倍数
- char ciXPelsPerMeter[4];//目标设备的水平像素数/米
- char ciYPelsPerMeter[4];//目标设备的垂直像素数/米
- char ciClrUsed[4]; //位图使用调色板的颜色数
- char ciClrImportant[4]; //指定重要的颜色数,当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要
- }__attribute__((packed)) BITMAPINFOHEADER;
- typedef struct
- {
- unsigned short blue;
- unsigned short green;
- unsigned short red;
- unsigned short reserved;
- }__attribute__((packed)) PIXEL;//颜色模式RGB
- BITMAPFILEHEADER FileHead;
- BITMAPINFOHEADER InfoHead;
- static char *fbp = 0;
- static int xres = 0;
- static int yres = 0;
- static int bits_per_pixel = 0;
- int show_bmp();
- int main ( int argc, char *argv[] )
- {
- int fbfd = 0;
- struct fb_var_screeninfo vinfo;
- struct fb_fix_screeninfo finfo;
- long int screensize = 0;
- struct fb_bitfield red;
- struct fb_bitfield green;
- struct fb_bitfield blue;
- //打开显示设备
- fbfd = open("/dev/fb0", O_RDWR);
- if (!fbfd)
- {
- printf("Error: cannot open framebuffer device.\n");
- exit(1);
- }
- if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
- {
- printf("Error:reading fixed information.\n");
- exit(2);
- }
- if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
- {
- printf("Error: reading variable information.\n");
- exit(3);
- }
- printf("R:%d,G:%d,B:%d \n", vinfo.red, vinfo.green, vinfo.blue );
- printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
- xres = vinfo.xres;
- yres = vinfo.yres;
- bits_per_pixel = vinfo.bits_per_pixel;
- //计算屏幕的总大小(字节)
- screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
- printf("screensize=%d byte\n",screensize);
- //对象映射
- 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(4);
- }
- printf("sizeof file header=%d\n", sizeof(BITMAPFILEHEADER));
- printf("into show_bmp function\n");
- //显示图像
- show_bmp();
- //删除对象映射
- munmap(fbp, screensize);
- close(fbfd);
- return 0;
- }
- int show_bmp()
- {
- FILE *fp;
- int rc;
- int line_x, line_y;
- long int location = 0, BytesPerLine = 0;
- char tmp[1024*10];
- fp = fopen( "./niu.bmp", "rb" );
- if (fp == NULL)
- {
- return( -1 );
- }
- rc = fread( &FileHead, sizeof(BITMAPFILEHEADER),1, fp );
- if ( rc != 1)
- {
- printf("read header error!\n");
- fclose( fp );
- return( -2 );
- }
- //检测是否是bmp图像
- if (memcmp(FileHead.cfType, "BM", 2) != 0)
- {
- printf("it‘s not a BMP file\n");
- fclose( fp );
- return( -3 );
- }
- rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );
- if ( rc != 1)
- {
- printf("read infoheader error!\n");
- fclose( fp );
- return( -4 );
- }
- //跳转的数据区
- fseek(fp, FileHead.cfoffBits, SEEK_SET);
- //每行字节数
- BytesPerLine = (InfoHead.ciWidth * InfoHead.ciBitCount + 31) / 32 * 4;
- line_x = line_y = 0;
- //向framebuffer中写BMP图片
- while(!feof(fp))
- {
- PIXEL pix;
- unsigned short int tmp;
- rc = fread( (char *)&pix, 1, sizeof(PIXEL), fp);
- if (rc != sizeof(PIXEL))
- break;
- location = line_x * bits_per_pixel / 8 + (InfoHead.ciHeight - line_y - 1) * xres * bits_per_pixel / 8;
- //显示每一个像素
- *(fbp + location + 0)=pix.blue;
- *(fbp + location + 1)=pix.green;
- *(fbp + location + 2)=pix.red;
- *(fbp + location + 3)=pix.reserved;
- line_x++;
- if (line_x == InfoHead.ciWidth )
- {
- line_x = 0;
- line_y++;
- if(line_y == InfoHead.ciHeight)
- break;
- }
- }
- fclose( fp );
- return( 0 );
- }
注意:上面的程序只在framebuffer上显示图片,却没有删除刷新屏幕,可以使用下面的命令恢复屏幕
保存屏幕信息:dd if=/dev/fb0 of=fbfile 或: cp /dev/fb0 fbfile
恢复屏幕信息:dd if=fbfile of=/dev/fb0 或: cat fbfile > /dev/fb0
以上是关于Linux下读取framebuffer(/dev/fb0)出来的数据全部是0,为啥会这样的主要内容,如果未能解决你的问题,请参考以下文章