📄 一个linux下的framebuffer的例子.htm
字号:
border=0><FONT color=#ff6600>减小字体</FONT></A> <A title=增大字体
style="CURSOR: hand; POSITION: relative"
onclick='if(newasp_fontsize<64){NewaspContentLabel.style.fontSize=(++newasp_fontsize)+"pt";NewaspContentLabel.style.lineHeight=(++newasp_lineheight)+"pt";}'><IMG
height=15 src="一个linux下的framebuffer的例子.files/2.gif" width=15
border=0><FONT color=#ff6600>增大字体</FONT></A> </P>
<DIV class=ContentFont id=NewaspContentLabel
style="PADDING-RIGHT: 10px; DISPLAY: block; PADDING-LEFT: 10px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px"><FONT
id=font_word
style="FONT-SIZE: 14px; FONT-FAMILY: 宋体, Verdana, Arial, Helvetica, sans-serif"><SPAN
class=content>摘要:<BR><BR>通过一个一个framebuffer例子,复习了内存分配的应用。其中的framebuffer例子为网上流行的(确实有bug的),在编译运行的过程中又重新温习了好多差不多已经被遗忘的知识点,写出来和大家分享!<BR>---------------------------------------------------------------------------------------------------------------------<BR>声明:<BR>
此文为原创,欢迎转载,转载请保留如下信息<BR> 作者:聂飞(afreez)<BR>
联系方式:<A href="mailto:afreez@sina.com"><FONT
color=#000000>afreez@sina.com</FONT></A> (欢迎与作者交流)<BR>
初次发布时间:2006-06-08<BR>
不经本人同意,不得用语商业或赢利性质目的,否则,作者有权追究相关责任!<BR>-----------------------------------------------------------------------------<BR><BR>例子实现了直接写屏的功能,即把屏幕清空(变黑),程序的流程大致为:打开一个FrameBuffer设备;通过mmap调用把显卡的物理内存空间映射到用户空间;通过映射关系直接写内存。<BR><BR><BR><BR>头文件<BR><BR>fbtools.h<BR><BR>#ifndef
_FBTOOLS_H_<BR><BR>#define _FBTOOLS_H_<BR><BR><BR><BR>#include
<linux/fb.h><BR><BR><BR><BR>//a framebuffer device
structure;<BR><BR>typedef struct fbdev{<BR><BR>
int fb;<BR><BR>
unsigned long fb_mem_offset;<BR><BR>
unsigned long fb_mem;<BR><BR>
struct fb_fix_screeninfo fb_fix;<BR><BR>
struct fb_var_screeninfo fb_var;<BR><BR>
char dev[20];<BR><BR>} FBDEV,
*PFBDEV;<BR><BR><BR><BR>//open & init a frame buffer<BR><BR>//to
use this function,<BR><BR>//you must set
FBDEV.dev="/dev/fb0"<BR><BR>//or "/dev/fbX"<BR><BR>//it's your frame
buffer.<BR><BR>int fb_open(PFBDEV pFbdev);<BR><BR><BR><BR>//close a
frame buffer<BR><BR>int fb_close(PFBDEV
pFbdev);<BR><BR><BR><BR>//get display depth<BR><BR>int
get_display_depth(PFBDEV pFbdev);<BR><BR><BR><BR><BR><BR>//full
screen clear<BR><BR>void fb_memset(void *addr, int c, size_t
len);<BR><BR><BR><BR>#endif<BR><BR><BR><BR>测试文件,其中深颜色的注释部分为在我机器上测得的结果<BR><BR>fbtools.c<BR><BR>代码:<BR><BR><BR><BR>#include
<stdio.h><BR><BR>#include <stdlib.h><BR><BR>#include
<fcntl.h><BR><BR>#include <unistd.h><BR><BR>#include
<string.h><BR><BR>#include <sys/ioctl.h><BR><BR>#include
<sys/mman.h><BR><BR>#include
<asm/page.h><BR><BR><BR><BR>#include
"fbtools.h"<BR><BR><BR><BR>#define TRUE
1<BR><BR>#define FALSE 0<BR><BR>#define
MAX(x,y) ((x)>(y)?(x):(y))<BR><BR>#define MIN(x,y)
((x)<(y)?(x):(y))<BR><BR><BR><BR>//open & init
a frame buffer<BR><BR>int fb_open(PFBDEV
pFbdev)<BR><BR>{<BR><BR>
pFbdev->fb = open(pFbdev->dev, O_RDWR);//
pFbdev->fb==3<BR><BR>
if(pFbdev->fb < 0)<BR><BR>
{<BR><BR>
printf("Error opening %s: %m. Check kernel config\n",
pFbdev->dev);<BR><BR>
return FALSE;<BR><BR>
}<BR><BR> if
(-1 ==
ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))<BR><BR>
{<BR><BR>
printf("ioctl
FBIOGET_VSCREENINFO\n");<BR><BR>
return FALSE;<BR><BR>
}<BR><BR>
if (-1 ==
ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))<BR><BR>
{<BR><BR>
printf("ioctl
FBIOGET_FSCREENINFO\n");<BR><BR>
return FALSE;<BR><BR>
}<BR><BR>
<BR><BR> //map physics address to
virtual address<BR><BR> //
pFbdev->fb_fix.smem_start=f0000000<BR><BR>
pFbdev->fb_mem_offset = (unsigned
long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);<BR><BR>//
pFbdev->fb_fix.smem_len=100 0000
pFbdev->fb_mem_offset=0<BR><BR>// pFbdev->fb_mem
=0<BR><BR> pFbdev->fb_mem =
(unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len
+<BR><BR>
pFbdev->fb_mem_offset,<BR><BR>
PROT_READ | PROT_WRITE,
MAP_SHARED, pFbdev->fb, 0);<BR><BR>
if (-1L == (long) pFbdev->fb_mem)<BR><BR>
{<BR><BR>
printf("mmap error! mem:%d
offset:%d\n", pFbdev->fb_mem,<BR><BR>
pFbdev->fb_mem_offset);<BR><BR>
return FALSE;<BR><BR>
}<BR><BR>
<BR><BR> return
TRUE;<BR><BR>}<BR><BR><BR><BR>//close frame buffer<BR><BR>int
fb_close(PFBDEV pFbdev)<BR><BR>{<BR><BR>
close(pFbdev->fb);<BR><BR>
pFbdev->fb=-1;<BR><BR>}<BR><BR><BR><BR>//get display
depth<BR><BR>int get_display_depth(PFBDEV
pFbdev);<BR><BR>{<BR><BR>
if(pFbdev->fb<=0)<BR><BR>
{<BR><BR>
printf("fb device not open, open it
first\n");<BR><BR>
return FALSE;<BR><BR>
}<BR><BR> return
pFbdev->fb_var.bits_per_pixel;<BR><BR>}<BR><BR><BR><BR>//full
screen clear<BR><BR>void fb_memset (void *addr, int c, size_t
len)<BR><BR>{<BR><BR> memset(addr, c,
len);<BR><BR>}<BR><BR><BR><BR>//use by test<BR><BR>#define
DEBUG<BR><BR>#ifdef DEBUG<BR><BR>main()<BR><BR>{<BR><BR>
FBDEV fbdev;<BR><BR>
memset(&fbdev, 0, sizeof(FBDEV));<BR><BR>
strcpy(fbdev.dev,
"/dev/fb0");<BR><BR>
if(fb_open(&fbdev)==FALSE)<BR><BR>
{<BR><BR>
printf("open frame buffer
error\n");<BR><BR>
return;<BR><BR>
}<BR><BR>
//注意,下面一行有bug<BR><BR>
fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0,
fbdev.fb_fix.smem_len);<BR><BR>
<BR><BR>
fb_close(&fbdev);<BR><BR>}<BR><BR>#endif<BR><BR>编译<BR><BR>如果对上述代码直接进行编译的话,是不能成功的,即会出现类似下面的编译错误<BR><BR>#gcc
–o fbtools fbtools.c<BR><BR>fbtools.c: In function
`main`<BR><BR>fbtools.c:89:warning:passing arg 1 of `fb_memset`
makes pointer from integer without a
cast<BR><BR><BR><BR>对有问题的fbtools.c中的第89行代码(即加粗的有注释的那一行)进行如下操作<BR><BR>修改为:<BR><BR>fb_memset((void
*)(fbdev.fb_mem+fbdev.fb_mem_offset), 0,
fbdev.fb_fix.smem_len);<BR><BR>或者<BR><BR>unsigned long
temp;<BR><BR>temp=
fbdev.fb_mem+fbdev.fb_mem_offset;<BR><BR>fb_memset((void *)temp, 0,
fbdev.fb_fix.smem_len);<BR><BR><BR><BR>可以成功编译成功<BR><BR><BR><BR>而修改为:<BR><BR>fb_memset((&)(fbdev.fb_mem+fbdev.fb_mem_offset),
0, fbdev.fb_fix.smem_len);<BR><BR>或者<BR><BR>unsigned long
temp;<BR><BR>temp=
fbdev.fb_mem+fbdev.fb_mem_offset;<BR><BR>fb_memset((&)temp, 0,
fbdev.fb_fix.smem_len);<BR><BR><BR><BR>会输出:段错误<BR><BR><BR><BR>分析<BR><BR>函数原形为:void
fb_memset (void *addr, int c, size_t
len)<BR><BR>而fbtools.c:89调用时传递的参数为:<BR><BR>fb_memset(fbdev.fb_mem+fbdev.fb_mem_offset,
0,
fbdev.fb_fix.smem_len);<BR><BR>fbdev.fb_mem和fbdev.fb_mem_offset都是unsigned
long类型的变量,它们的计算结果保存在一个临时的栈空间,传递调用时,其临时的地址是不能够传递到被调用的函数的,所以编译是同不过的。具体的可以参考内存分配的相关知识,记得《effective
c++》一书里讲的很详细,可以参考。<BR><BR>至于修改后的:<BR><BR>fb_memset((&)temp, 0,
fbdev.fb_fix.smem_len);<BR><BR>编译出现段错误,也是很好理解的,因为(&)temp不等于(void
*)temp,也不等于<BR><BR>(void
*)(fbdev.fb_mem+fbdev.fb_mem_offset),具体原因读者可以对照《effective
c++》思考。</SPAN> </FONT></DIV>
<DIV></DIV></TD></TR>
<TR>
<TD
style="PADDING-RIGHT: 10px; DISPLAY: block; PADDING-LEFT: 10px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px"
align=right bgColor=#f7f7f7 height=25>[
<SCRIPT language=JavaScript
src="一个linux下的framebuffer的例子.files/Hits.htm"></SCRIPT>
] [<A href="javascript:history.go(-1)">返回上一页</A>] [<A
href="javascript:window.print()">打 印</A>] [<A
href="http://www.fixdown.com/wz/user/favorite.asp?action=add&topic=一个linux下的framebuffer的例子">收
藏</A>]</TD></TR>
<TR>
<TD
style="PADDING-RIGHT: 10px; DISPLAY: block; PADDING-LEFT: 10px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px">
<DIV>上一篇文章:<A
href="http://www.fixdown.com/wz/article/14/21/2006/57424.htm">MySQL使用tips</A></DIV>
<DIV>下一篇文章:<A
href="http://www.fixdown.com/wz/article/23/25/2006/57426.htm">为
Linux 手动下载和安装 Java Runtime Environment (JRE)
的说明</A></DIV></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=575 border=0>
<TBODY>
<TR>
<TD class=titlebg1>∷相关文章评论∷ (评论内容只代表网友观点,与本站立场无关!) [<A
href="http://www.fixdown.com/wz/article/comment.asp?ArticleID=57425"
target=_blank>更多评论</A>...]</TD></TR>
<TR vAlign=top>
<TD></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><!-- 页面底部开始 -->
<TABLE class=tableborder height=34 cellSpacing=0 cellPadding=0 width=778
align=center border=0>
<TBODY>
<TR>
<TD height=5></TD></TR>
<TR>
<TD class=linebar height=8></TD></TR>
<TR>
<TD height=5></TD></TR>
<TR>
<TD class=tablebody align=middle height=16><A class=navmenu
href="http://www.fixdown.com/wz/link/" target=_blank>友情连接</A> - <A
class=navmenu
href="http://www.fixdown.com/wz/support/sitemap.asp">网站地图</A> -</TD></TR>
<TR>
<TD height=1></TD></TR></TBODY></TABLE>
<SCRIPT language=javascript
src="一个linux下的framebuffer的例子.files/Std_StranJF.Js"></SCRIPT>
<!-- 页面底部结束 -->
<SCRIPT src="一个linux下的framebuffer的例子.files/count.htm"
type=text/javascript></SCRIPT>
<SPAN class=spanclass id=span_ad_01></SPAN>
<SCRIPT>ad_01.innerHTML=span_ad_01.innerHTML;span_ad_01.innerHTML="";</SCRIPT>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -