对FrameBuffer的简单解释和用法示例

news/2024/7/8 5:23:27 标签: fp, struct, 图形, 存储, 数据结构, unix

大家都知道Unix/Linux系统是由命令驱动的。那么最基本的系统是命令行的(就是想DOS一样的界面)。X-Window-System是Unix/Linux上的图形系统,它是通过X-Server来控制硬件的。但有一些Linux的发行版在引导的时候就会在屏幕上出现图形,这时的图形是不可能由X来完成的,那是什么机制呢?答案是FrameBuffer。
FrameBuffer不是一个图形系统,更不是窗口系统。它比X要低级,简单来说FrameBuffer就是一种机制的实现。这种机制是把屏幕上的每个点映射成一段线性内存空间,程序可以简单的改变这段内存的值来改变屏幕上某一点的颜色。X的高度可移植性就是来自于这种机制,不管是在那种图形环境下,只要有这种机制的实现就可以运行X。所以在几乎所有的平台上都有相应的X版本的移植。
好了,闲话少说,下面我们来看看可以利用FrameBuffer来干点什么。首先看看你是否有了相应的驱动:找一下在/dev/下是否有fb*这个设备文件,这是个字符类的特殊文件。

代码:
   
ls -l /dev/fb0 (Enter) crw-rw---- 1 root video 29, 0 Jan 27 15:32 /dev/fb0

如果没有这个文件也可以找找其他的比如:/dev/fb1,/dev/fb2...如果找不到这些文件,那就得重新编译内核了。下面假设存在这个文件/dev/fb0,这就是FrameBuffer的设备文件。
有了这个我们可以play with FrameBuffer了。(一下的操作不一定要在X下,可以在启动了FrameBuffer的虚拟控制台下)

代码:
   
cat /dev/fb0 > sreensnap ls -l sreensnap -rw-r--r-- 1 wsw wsw 6291456 Jan 27 21:30 sreensnap

我们得到了一个恰好6M的文件,再做下面的操作:

代码:
   
clear /*清楚屏幕的输出*/ cat sreensnap > /dev/fb0

是不是奇怪的事情发生了?好像是中了病毒一般?屏幕又恢复了以前的状态?不用着急,

代码:
   
clear

这样屏幕就正常了。

通过以上的操作,我想你也猜到了。文件/dev/fb0就是控制屏幕上的每一点的颜色的文件。我们可以写程序来改变这个文件的内容,就可以方便的在屏幕上画图了:-)

我下面就来写一个小程序,探测一下屏幕的属性。

代码:
   
#include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <linux/fb.h> #include <sys/mman.h> int main () { int fp=0; struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; fp = open ("/dev/fb0",O_RDWR); if (fp < 0){ printf("Error : Can not open framebuffer device/n"); exit(1); } if (ioctl(fp,FBIOGET_FSCREENINFO,&finfo)){ printf("Error reading fixed information/n"); exit(2); } if (ioctl(fp,FBIOGET_VSCREENINFO,&vinfo)){ printf("Error reading variable information/n"); exit(3); } printf("The mem is :%d/n",finfo.smem_len); printf("The line_length is :%d/n",finfo.line_length); printf("The xres is :%d/n",vinfo.xres); printf("The yres is :%d/n",vinfo.yres); printf("bits_per_pixel is :%d/n",vinfo.bits_per_pixel); close (fp); }

struct fb_var_screeninfo 和 struct fb_fix_screeninfo 两个数据结构是在/usr/include/linux/fb.h中定义的,里面有些有趣的值:(都是无符号32位的整数)

在fb_fix_screeninfo中有
__u32 smem_len 是这个/dev/fb0的大小,也就是内存大小。
__u32 line_length 是屏幕上一行的点在内存中占有的空间,不是一行上的点数。
在fb_var_screeninfo 中有
__u32 xres ,__u32 yres 是x和y方向的分辨率,就是两个方向上的点数。
__u32 bits_per_pixel 是每一点占有的内存空间。

把上面的程序编译以后运行,在我的机器上的结果如下:

代码:
      
The mem is :6291456 The line_length is :4096 The xres is :1024 The yres is :768 bits_per_pixel is :32

内存长度恰好是6M,每行占有4M的空间,分辨率是1024x768,色彩深度是32位。细心的你可能已经发现有些不对。屏幕上的点有1024x768=786432个,每个点占有32比特。屏幕一共的占有内存数为32x786432=25165824 就是3145728字节,恰好是3M但是上面的程序告诉我们有6M的存储空间。这是因为在现代的图形系统中大多有缓冲技术,显存中存有两页屏幕数据,这是方便快速的改变屏幕内容实现动画之类比较高的要求。关于这种缓冲技术有点复杂,我们目前先不讨论。对于我们来说只有这3M内存来存放这一个屏幕的颜色数据。
好了,现在你应该对FrameBuffer有一个大概的了解了吧。那么接下来你一定会想在屏幕上画一些东西,让我们先从画一个点开始吧。先说说我的想法:在类Unix系统中,一切东西都是文件。我们对屏幕的读写就可以转换成对/dev/fb0的读写。那么就把/dev/fb0用open打开,再用lseek定位要读写的位置,最后调用read或者write来操作。通过这么一大段的操作我们才完成了对一个点的读或者写。这种方法开销太大了。还有一种方法,我们把/dev/fb0映射到程序进程的内存空间中来,然后得到一个指向这段存储空间的指针,这样就可以方便的读写了。但是我们要知道能映射多少和该映射多少,这能很方便的从上面一个程序得出的参数来决定。
下面是程序代码:

代码:
      
#include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <linux/fb.h> #include <sys/mman.h> int main () { int fp=0; struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; long screensize=0; char *fbp = 0; int x = 0, y = 0; long location = 0; fp = open ("/dev/fb0",O_RDWR); if (fp < 0){ printf("Error : Can not open framebuffer device/n"); exit(1); } if (ioctl(fp,FBIOGET_FSCREENINFO,&finfo)){ printf("Error reading fixed information/n"); exit(2); } i (ioctl(fp,FBIOGET_VSCREENINFO,&vinfo)){ p "Error reading variable information/n"); e ; screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8 /*这就是把fp所指的文件中从开始到screensize大小的内容给映射出来,得到一个指向这块空间的指针*/ fb (char *) mma (0 creensize, PROT_READ | PROT_WRITE, MAP_SHARED, fp,0);

因为这是对线性存储空间的读写,所以代码有点不清晰,不易理解。但是有了这个基本的代码实现,我们可以很容易写一些DrawPoint之类的函数去包装一下低层的对线性存储空间的读写。但是有了画点的程序,再写出画线画圆的函数就不是非常困难了。

这些就是我对FrameBuffer的初步研究,匆忙之间写些东西不成文章,以后要写些更高级一点的函数的实现。

来源:http://blog.csdn.net/guyun_shine/article/details/6019596


http://www.niftyadmin.cn/n/1736423.html

相关文章

mmap与内存管理

mmap与内存管理- mmap系统调用的编程实例 收藏 1 mmap的使用 mmap地址映射是Linux系统提供的一种功能强大的系统调用&#xff0c;最典型的应用是用于显卡内存的映射。同样&#xff0c;对于普通的硬盘文件也可以进行mmap系统调用。 #include <sys/mman.h> void * m…

linux spi驱动分析

关于spi的学习&#xff0c;我觉得最好的方法还是看Linux的源代码&#xff0c;主要是driver/spi/spi.c(h)&#xff0c;spidev.c(h)。spi dev的示例可以看看at25.c&#xff0c;spi总线的示例可以看omap_uwire或者spi_s3c24xx.c和spi_s3c24xx_gpio.c。在看这些代码之前&#xff0c…

小议大小端模式对C语言的共用体结构的影响

小议大小端模式对C语言的共用体结构的影响 1、一些问题 问题1 view plaincopy to clipboardprint?#include "stdio.h" union { int i; char ch[2]; }key; main() { key.i65*25666; printf("%c\t%c\n",key.ch[0],key.ch[1]); …

Linux下SPI驱动分析

Linux下SPI总线驱动有通用接口&#xff0c;一般的SPI设备驱动使用这个驱动接口实现设备驱动。分析驱动最好是先了解核心代码&#xff0c;然后从具体设备分析入手&#xff0c;然后从下至上&#xff0c;了解整个框架&#xff0c;再从上到下分析&#xff0c;理解透彻。 以下分析内…

Linux驱动修炼之道-SPI驱动框架源码分析(上)

努力成为linux kernel hacker的人李万鹏原创作品&#xff0c;为梦而战。转载请标明出处 http://blog.csdn.net/woshixingaaa/archive/2011/06/29/6574215.aspx Linux驱动修炼之道-SPI驱动框架源码分析(中) Linux驱动修炼之道-SPI驱动框架源码分析(下) SPI协议是一种同步的串…

Linux驱动修炼之道-SPI驱动框架源码分析(中)

努力成为linux kernel hacker的人李万鹏原创作品&#xff0c;为梦而战。转载请标明出处 http://blog.csdn.net/woshixingaaa/archive/2011/06/29/6574220.aspx 这篇来分析spi子系统的建立过程。 嵌入式微处理器访问SPI设备有两种方式&#xff1a;使用GPIO模拟SPI接口的工作时序…

Linux驱动修炼之道-SPI驱动框架源码分析(下)

努力成为linux kernel hacker的人李万鹏原创作品&#xff0c;为梦而战。转载请标明出处 http://blog.csdn.net/woshixingaaa/article/details/6574224 这篇文档主要介绍spi数据传输过程。 当应用层要向设备传输数据的时候&#xff0c;会通过ioctl向设备驱动发送传输数据的…

内核中的基本C库函数 位操作

位操作 set_bit 在位图中原子地设置某一位 void set_bit (int nr, volatile void * addr) nr为要设置的位&#xff0c;addr为位图的起始地址 这个函数是原子操作&#xff0c;如果不需要原子操作&#xff0c;则调用__set_bit函数&#xff0c;nr可以任意大&#xff0c;位图的…