LinuxSir.Org  
| 网站首页 | 论坛帮助 |

欢迎来到LinuxSir.Org!
您还未登录,请登录后查看论坛,或者点击论坛上方的注册链接注册新账号。


发表新主题 回复
精华主题  
主题工具
旧 06-01-28, 01:03 第 1 帖
wsw
 
wsw 的头像
 
 
注册会员  
  注册日期: Aug 2005
  帖子: 484
  精华: 2
 

标题: 对FrameBuffer的一夜hack。。。


大家都知道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); } if (ioctl(fp,FBIOGET_VSCREENINFO,&vinfo)){ printf("Error reading variable information\n"); exit(3); } screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; /*这就是把fp所指的文件中从开始到screensize大小的内容给映射出来,得到一个指向这块空间的指针*/ fbp =(char *) mmap (0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fp,0); if ((int) fbp == -1) { printf ("Error: failed to map framebuffer device to memory.\n"); exit (4); } /*这是你想画的点的位置坐标,(0,0)点在屏幕左上角*/ x = 100; y = 100; location = x * (vinfo.bits_per_pixel / 8) + y * finfo.line_length; *(fbp + location) = 100; /* 蓝色的色深 */ /*直接赋值来改变屏幕上某点的颜色*/ *(fbp + location + 1) = 15; /* 绿色的色深*/ *(fbp + location + 2) = 200; /* 红色的色深*/ *(fbp + location + 3) = 0; /* 是否透明*/ munmap (fbp, screensize); /*解除映射*/ close (fp); /*关闭文件*/ return 0; }
因为这是对线性存储空间的读写,所以代码有点不清晰,不易理解。但是有了这个基本的代码实现,我们可以很容易写一些DrawPoint之类的函数去包装一下低层的对线性存储空间的读写。但是有了画点的程序,再写出画线画圆的函数就不是非常困难了。

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







__________________
在未上大学时,我一直以为自己是个天才。
正在上大学时,我以为自己将是个天才。
读完大学后,我才发现自己是并且从来就是一个彻头彻尾的傻瓜,
自大。。。浮躁。。。终究一无是处。

此帖于 06-09-09 01:06 被 wsw 编辑.
  wsw 当前离线   回复时引用此帖
旧 06-01-28, 01:16 第 2 帖
biinn
 
biinn 的头像
 
 
注册会员  
  注册日期: Nov 2005
  我的住址: 花生屯->搬走了
  帖子: 1,374
  精华: 0
 

好东西。感到好熟悉,十几年前在DOS下写图形界面的程序就是读写0xa000那段内存,输出汉字也没问题。原来linux也能这样用。有时间琢磨琢磨。
  biinn 当前离线   回复时引用此帖
旧 06-01-28, 11:15 第 3 帖
Wallace.lee
 
 
 
注册会员  
  注册日期: Feb 2005
  帖子: 222
  精华: 0
 

好贴。支持你的努力
  Wallace.lee 当前离线   回复时引用此帖
旧 06-01-28, 12:58 第 4 帖
memory
 
 
 
注册会员  
  注册日期: May 2004
  帖子: 928
  精华: 0
 

好文章,让我了解了fb是怎么工作的。
  memory 当前离线   回复时引用此帖
旧 06-01-30, 11:10 第 5 帖
wide288
 
wide288 的头像
 
 
注册会员  
  注册日期: Nov 2002
  我的住址: 辽宁省
  帖子: 2,727
  精华: 15
 

Gtk Qt 是不是通过操作 fb 来画图的呢?
这样画的图在鼠标移过时,图就会被更新,那更新出来的图,是存在那里的呢?
fb 里存放的数据是否存有正在看的电影的显示呢?







__________________
my new pc: Intel Duo 1.86GHz/ 2G Mem/ GIGABYTE 965P-S3/ 250G hardware/ 艾尔莎 影雷者 7600/ DVD write rom/ netcard Marvell 88E8056/ 联志机箱/

http://gimpstore.cn/
追求一种自由,共享,与技术的极限和快乐的生活!
gimp 教程
http://www.linux-wiki.cn/work/gimp/
  wide288 当前离线   回复时引用此帖
旧 06-01-31, 20:10 第 6 帖
skykingf
 
skykingf 的头像
 
 
注册会员  
  注册日期: Jul 2005
  帖子: 1,198
  精华: 0
 

强人+强贴..........







__________________
笔记本 Debian linux 3.1 英文界面
Windows XP Pro English Edition
IBM T23 PIII1.2G 512M 80Gb

台式机 Fedora Core 6 英文界面
Windows Server 2003 Standard
Dell GX620 P IV 3.0G 512M 80Gb SATA

服务器 Fedora 8 英文界面
Windows XP En Oem
Dell GX270 P IV 2.8G 512M 80Gb SATA
  skykingf 当前离线   回复时引用此帖
旧 06-01-31, 23:05 第 7 帖
wsw
 
wsw 的头像
 
 
注册会员  
  注册日期: Aug 2005
  帖子: 484
  精华: 2
 

framebuffer 要比X-window-system低级。而GTK和QT是建立在Xlib上的,至于如何来实现鼠标那应该是X-server的事情了,在安装X-window-system(debian)时会让你选择要不要内核的framebuffer支持,理论上选和不选都可以。如果不选,X会用它自带的驱动来实现对线性内存空间的读写改变屏幕显示。

这只是一个机制,实现不一定非要framebuffer不可。但在Linux(kernel>2.2)上用framebuffer来实现X总是可以的。
  wsw 当前离线   回复时引用此帖
旧 06-02-01, 17:02 第 8 帖
d00m3d
 
d00m3d 的头像
 
 
资深版主  
  注册日期: Nov 2004
  帖子: 14,541
  精华: 10
 

嘿嘿,又长见识了,望楼主多分享经验及心得,值得加精鼓励







__________________
nO ^^4+73R wH1<h d!5+R0z j00 42E U$1N9 7r% LpHZ 4+ l3457 oN(&
  d00m3d 当前离线   回复时引用此帖
旧 06-02-04, 18:23 第 9 帖
nbyh
 
nbyh 的头像
 
 
注册会员  
  注册日期: Nov 2004
  帖子: 279
  精华: 0
 

希望多看到这种文章







__________________
Athlon 2000+ / sata 80G / Abit Kv7 /nv Fx5200U
Debian GNOME / FreeBSD KDE
做一件令自己感动是事情……
  nbyh 当前离线   回复时引用此帖
旧 06-02-04, 19:13 第 10 帖
rushrush 美女
 
rushrush 的头像
 
 
注册会员  
  注册日期: Aug 2004
  帖子: 666
  精华: 0
 

有个叫 direct frame buffer 的项目,做的类似于楼主所说的事情:
http://www.directfb.org/







__________________
by 断了的猫 (arch linux)
blog: http://rushrush.cublog.cn
新浪微博: http://t.sina.com.cn/mao8421
  rushrush 当前离线   回复时引用此帖
旧 06-02-05, 14:28 第 11 帖
homesp
 
homesp 的头像
 
 
注册会员  
  注册日期: Jun 2004
  我的住址: 天津
  帖子: 1,488
  精华: 1
 

谢谢楼主分享,回去好好研究一下







__________________
Debian Testing

Dell D630
2G RAM
Nvidia Quadro NVS 135m display card
  homesp 当前离线   回复时引用此帖
旧 06-02-05, 14:41 第 12 帖
hway
 
 
 
注册会员  
  注册日期: Aug 2004
  帖子: 18
  精华: 0
 

qt的嵌入式版qte使用的是framebuffer
  hway 当前离线   回复时引用此帖
旧 10-01-06, 16:47 第 13 帖
lishubing1126
 
 
 
注册会员  
  注册日期: Dec 2009
  帖子: 1
  精华: 0
 

不错不错,才开始学
  lishubing1126 当前离线   回复时引用此帖
旧 10-01-31, 13:18 第 14 帖
cqpwx
 
cqpwx 的头像
 
 
注册会员  
  注册日期: Sep 2003
  帖子: 127
  精华: 0
 

后面的分析写的很好,简单易懂,学习了,谢谢楼主
  cqpwx 当前离线   回复时引用此帖
旧 10-05-01, 11:54 第 15 帖
crazypenguin 帅哥
 
crazypenguin 的头像
 
 
注册会员  
  注册日期: Sep 2008
  帖子: 116
  精华: 0
 

好喜欢!!!







__________________
Sometimes I wish I could save you and there're so many things that I want you to know。
  crazypenguin 当前离线   回复时引用此帖
发表新主题 回复


主题工具

发帖规则
您 [不可以] 发表新主题
您 [不可以] 回复主题
您 [不可以] 上传附件
您 [不可以] 编辑您的帖子

已 [启用] BB 代码
已 [启用] 表情符号
已 [启用] IMG 代码
已 [禁用] HTML 代码
[论坛跳转…]


所有时间均为[北京时间]。现在的时间是 06:19


Powered by vBulletin 版本 3.6.8
版权所有 ©2000 - 2012, Jelsoft Enterprises Ltd.
官方中文技术支持: vBulletin 中文
版权所有 ©2002 - 2011, LinuxSir.Org