现在的位置: 首页 > 综合 > 正文

Framebuffer的介绍

2014年08月07日 ⁄ 综合 ⁄ 共 2777字 ⁄ 字号 评论关闭

 

FramebufferLinux中是作为设备来实现的,它是对图形硬件的一种抽象[1],代表着显卡中的帧缓冲区(Framebuffer)。通过Framebuffer设备,上层软件可以通过一个良好定义的软件接口访问图形硬件,而不需要关心底层图形硬件是如何工作的,比如,上层软件不用关心应该如何读写显卡寄存器,也不需要知道显卡中的帧缓冲区从什么地址开始,所有这些工作都由Framebuffer去处理,上层软件只需要集中精力在自己要做的事情上就是了。

Framebuffer的优点在于它是一种低级的通用设备,而且能够跨平台工作,比如Framebuffer既可以工作在x86平台上,也能工作在PPC平台上,甚至也能工作在m68kSPARC等平台上,在很多嵌入式设备上Framebuffer也能正常工作。诸如Minigui之类的GUI软件包也倾向于采用Framebuffer作为硬件抽象层(HAL)。

从用户的角度来看,Framebuffer设备与其它设备并没有什么不同。Framebuffer设备位于/dev下,通常设备名为fb*,这里*的取值从031。对于常见的计算机系统而言,32Framebuffer设备已经绰绰有余了(至少作者还没有看到过有32个监视器的计算机)。最常用到的Framebuffer设备是/dev/fb0。通常,使用Framebuffer的程序通过环境变量FRAMEBUFFER来取得要使用的Framebuffer设备,环境变量FRAMEBUFFER通常被设置为”/dev/fb0”

从程序员的角度来看,Framebuffer设备其实就是一个文件而已,可以像对待普通文件那样读写Framebuffer设备文件,可以通过mmap()将其映射到内存中,也可以通过ioctl()读取或者设置其参数,等等。最常见的用法是将Framebuffer设备通过mmap()映射到内存中,这样可以大大提高IO效率。

要在PC平台上启用Framebuffer,首先必须要内核支持,这通常需要重新编译内核。另外,还需要修改内核启动参数。在作者的系统上,为了启用Framebuffer,需要将/boot/grub/menu.lst中的下面这一行:

kernel /boot/vmlinuz-2.4.20-8 ro root=LABEL=/1

修改为

kernel /boot/vmlinuz-2.4.20-8 ro root=LABEL=/1 vga=0x0314

即增加了vga=0x0314这样一个内核启动参数。这个内核启动参数表示的意思是:Framebuffer设备的大小是800x600,颜色深度是16bits/像素。

下面,来了解一下如何编程使用Framebuffer设备。由于对Framebuffer设备的读写应该是不缓冲的,但是标准IO库默认是要进行缓冲的,因此通常不使用标准IO库读写Framebuffer设备,而是直接通过read()write()或者mmap()等系统调用来完成与Framebuffer有关的IO操作。又由于mmap()能够大大降低IO的开销,因此与Framebuffer设备有关的IO通常都是通过mmap()系统调用来完成的。mmap()的函数原型如下(Linux系统上的定义):

#include <sys/mman.h>

#ifdef _POSIX_MAPPED_FILES

 

void  mmap(void *start, size_t length, int prot , int flags, int fd,

       off_t offset);

 

int munmap(void *start, size_t length);

 

#endif

系统调用mmap()用来实现内存映射IO。所谓内存映射IO,是指将一个磁盘文件的内容与内存中的一个空间相映射。当从这个映射内存空间中取数据时,就相当于从文件中读取相应的字节,而当向此映射内存空间写入数据时,就相当于向磁盘文件中写入数据。这就是内存映射IO的含义。

具体到对mmap()而言,当调用成功时,返回值就是与磁盘文件建立了映射关系的内存空间的起始地址,当调用失败时,mmap()的返回值是-1。第一个参数start通常设置为0,表示由系统选择映射内存空间;第二个参数length指定了要映射的字节数;第三个参数指明了映射内存空间的保护属性,对于Framebuffer通常将其设置为PROT_READ
| PROT_WRITE
,表示既可读也可写;第四个参数flags指明了影响映射内存空间行为的标志,对于Framebuffer编程而言,要将flags设置为MAP_SHARED,表明当向映射内存空间写入数据时,将数据写入磁盘文件中;第五个参数fd是要映射的文件的文件描述符;第六个参数offset指明了要映射的字节在文件中的偏移量。

如果mmap()调用成功,就可以在程序中对得到的映射内存空间进行读写操作了。所有的读写都将由操作系统内核转换成IO操作。

在使用完映射内存空间之后,应当将其释放,这是通过munmap()系统调用完成的。munmap()的第一个参数是映射内存空间的起始地址,第二个参数length是映射内存空间的长度,单位为字节。如果释放成功,munmap()返回0,否则返回-1

如果应用程序需要知道Framebuffer设备的相关参数,必须通过ioctl()系统调用来完成。在头文件<linux/fb.h>中定义了所有的ioctl命令字,不过,最常用的ioctl命令字是下面这两个:FBIOGET_FSCREENINFOFBIOGET_VSCREENINFO,前者返回与Framebuffer有关的固定的信息,比如图形硬件上实际的帧缓存空间的大小、能否硬件加速等信息;而后者返回的是与Framebuffer有关的可变信息,之所以可变,是因为对同样的图形硬件,可以工作在不同的模式下,简单来讲,一个支持1024x768x24图形模式的硬件通常也能工作在800x600x16的图形模式下,可变的信息就是指Framebuffer的长度、宽度以及颜色深度等信息。这两个命令字相关的结构体有两个:struct
fb_fix_screeninfo
struct fb_var_screeninfo,这两个结构体都比较大,前者用于保存Framebuffer设备的固定信息,后者用于保存Framebuffer设备的可变信息。在调用ioctl()的时候,要用到这两个结构体。应用程序中通常要用到struct
fb_var_screeninfo
的下面这几个字段:xresyresbits_per_pixel,分别表示x轴的分辨率、y轴的分辨率以及每像素的颜色深度(颜色深度的单位为bit/pixel),其类型定义都是无符号32位整型数。

【上篇】
【下篇】

抱歉!评论已关闭.