与afreez一起学习DirectFB之:一个linux下的framebuffer例子的学问
生活随笔
收集整理的這篇文章主要介紹了
与afreez一起学习DirectFB之:一个linux下的framebuffer例子的学问
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
摘要:
通過(guò)一個(gè)一個(gè)framebuffer例子,復(fù)習(xí)了內(nèi)存分配的應(yīng)用。其中的framebuffer例子為網(wǎng)上流行的(確實(shí)有bug的),在編譯運(yùn)行的過(guò)程中又重新溫習(xí)了好多差不多已經(jīng)被遺忘的知識(shí)點(diǎn),寫出來(lái)和大家分享!
---------------------------------------------------------------------------------------------------------------------
聲明:
? ? 此文為原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)保留如下信息
? ? 作者:聶飛(afreez)
? ? 聯(lián)系方式:[email]afreez@sina.com[/email] (歡迎與作者交流)
? ? 初次發(fā)布時(shí)間:2006-06-08
? ? 不經(jīng)本人同意,不得用語(yǔ)商業(yè)或贏利性質(zhì)目的,否則,作者有權(quán)追究相關(guān)責(zé)任!
-----------------------------------------------------------------------------
例子實(shí)現(xiàn)了直接寫屏的功能,即把屏幕清空(變黑),程序的流程大致為:打開一個(gè)FrameBuffer設(shè)備;通過(guò)mmap調(diào)用把顯卡的物理內(nèi)存空間映射到用戶空間;通過(guò)映射關(guān)系直接寫內(nèi)存。
頭文件
fbtools.h
#ifndef _FBTOOLS_H_
#define _FBTOOLS_H_
#include <linux/fb.h>
//a framebuffer device structure;
typedef struct fbdev{
? ? ? ? ? int fb;
? ? ? ? ? unsigned long fb_mem_offset;
? ? ? ? ? unsigned long fb_mem;
? ? ? ? ? struct fb_fix_screeninfo fb_fix;
? ? ? ? ? struct fb_var_screeninfo fb_var;
? ? ? ? ? char dev[20];
} FBDEV, *PFBDEV;
//open & init a frame buffer
//to use this function,
//you must set FBDEV.dev="/dev/fb0"
//or "/dev/fbX"
//it's your frame buffer.
int fb_open(PFBDEV pFbdev);
//close a frame buffer
int fb_close(PFBDEV pFbdev);
//get display depth
int get_display_depth(PFBDEV pFbdev);
//full screen clear
void fb_memset(void *addr, int c, size_t len);
#endif
測(cè)試文件,其中深顏色的注釋部分為在我機(jī)器上測(cè)得的結(jié)果
fbtools.c
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <asm/page.h>
#include "fbtools.h"
#define TRUE ? ? ? 1
#define FALSE ? ? ? 0
#define MAX(x,y) ? ? ((x)>(y)?(x):(y))
#define MIN(x,y) ? ? ((x)<(y)?(x):(y))
//open & init a frame buffer
int fb_open(PFBDEV pFbdev)
{
? ? ? ? ? pFbdev->fb = open(pFbdev->dev, O_RDWR);// pFbdev->fb==3
? ? ? ? ? if(pFbdev->fb < 0)
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("Error opening %s: %m. Check kernel config\n", pFbdev->dev);
? ? ? ? ? ? ? ? ? ? return FALSE;
? ? ? ? ? }
? ? ? ? ? if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("ioctl FBIOGET_VSCREENINFO\n");
? ? ? ? ? ? ? ? ? ? return FALSE;
? ? ? ? ? }
? ? ? ? ? if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("ioctl FBIOGET_FSCREENINFO\n");
? ? ? ? ? ? ? ? ? ? return FALSE;
? ? ? ? ? }
? ? ? ?
? ? ? ? ? //map physics address to virtual address
? ? ? ? ? // pFbdev->fb_fix.smem_start=f0000000
? ? ? ? ? pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
// pFbdev->fb_fix.smem_len=100 0000 pFbdev->fb_mem_offset=0
// pFbdev->fb_mem =0
? ? ? ? ? pFbdev->fb_mem = (unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len +
? ? ? ? ? ? ? ? ? ? ? ? ? ? pFbdev->fb_mem_offset,
? ? ? ? ? ? ? ? ? ? PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0);
? ? ? ? ? if (-1L == (long) pFbdev->fb_mem)
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("mmap error! mem:%d offset:%d\n", pFbdev->fb_mem,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pFbdev->fb_mem_offset);
? ? ? ? ? ? ? ? ? ? return FALSE;
? ? ? ? ? }
? ? ? ?
? ? ? ? ? return TRUE;
}
//close frame buffer
int fb_close(PFBDEV pFbdev)
{
? ? ? ? ? close(pFbdev->fb);
? ? ? ? ? pFbdev->fb=-1;
}
//get display depth
int get_display_depth(PFBDEV pFbdev);
{
? ? ? ? ? if(pFbdev->fb<=0)
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("fb device not open, open it first\n");
? ? ? ? ? ? ? ? ? ? return FALSE;
? ? ? ? ? }
? ? ? ? ? return pFbdev->fb_var.bits_per_pixel;
}
//full screen clear
void fb_memset (void *addr, int c, size_t len)
{
? memset(addr, c, len);
}
//use by test
#define DEBUG
#ifdef DEBUG
main()
{
? ? ? ? ? FBDEV fbdev;
? ? ? ? ? memset(&fbdev, 0, sizeof(FBDEV));
? ? ? ? ? strcpy(fbdev.dev, "/dev/fb0");
? ? ? ? ? if(fb_open(&fbdev)==FALSE)
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("open frame buffer error\n");
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? }
? ? ? ? ? //注意,下面一行有bug
? ? ? ? ? fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
? ? ? ?
? ? ? ? ? fb_close(&fbdev);
}
#endif
編譯
如果對(duì)上述代碼直接進(jìn)行編譯的話,是不能成功的,即會(huì)出現(xiàn)類似下面的編譯錯(cuò)誤
#gcc –o fbtools fbtools.c
fbtools.c: In function `main`
fbtools.c:89:warning:passing arg 1 of `fb_memset` makes pointer from integer without a cast
對(duì)有問題的fbtools.c中的第89行代碼(即加粗的有注釋的那一行)進(jìn)行如下操作
修改為:
fb_memset((void *)(fbdev.fb_mem+fbdev.fb_mem_offset), 0, fbdev.fb_fix.smem_len);
或者
unsigned long temp;
temp= fbdev.fb_mem+fbdev.fb_mem_offset;
fb_memset((void *)temp, 0, fbdev.fb_fix.smem_len);
可以成功編譯成功
而修改為:
fb_memset((&)(fbdev.fb_mem+fbdev.fb_mem_offset), 0, fbdev.fb_fix.smem_len);
或者
unsigned long temp;
temp= fbdev.fb_mem+fbdev.fb_mem_offset;
fb_memset((&)temp, 0, fbdev.fb_fix.smem_len);
會(huì)輸出:段錯(cuò)誤
分析
函數(shù)原形為:void fb_memset (void *addr, int c, size_t len)
而fbtools.c:89調(diào)用時(shí)傳遞的參數(shù)為:
fb_memset(fbdev.fb_mem+fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
fbdev.fb_mem和fbdev.fb_mem_offset都是unsigned long類型的變量,它們的計(jì)算結(jié)果保存在一個(gè)臨時(shí)的棧空間,傳遞調(diào)用時(shí),其臨時(shí)的地址是不能夠傳遞到被調(diào)用的函數(shù)的,所以編譯是同不過(guò)的。具體的可以參考內(nèi)存分配的相關(guān)知識(shí),記得《effective c++》一書里講的很詳細(xì),可以參考。
至于修改后的:
fb_memset((&)temp, 0, fbdev.fb_fix.smem_len);
編譯出現(xiàn)段錯(cuò)誤,也是很好理解的,因?yàn)?&)temp不等于(void *)temp,也不等于
(void *)(fbdev.fb_mem+fbdev.fb_mem_offset),具體原因讀者可以對(duì)照《effective c++》思考。
通過(guò)一個(gè)一個(gè)framebuffer例子,復(fù)習(xí)了內(nèi)存分配的應(yīng)用。其中的framebuffer例子為網(wǎng)上流行的(確實(shí)有bug的),在編譯運(yùn)行的過(guò)程中又重新溫習(xí)了好多差不多已經(jīng)被遺忘的知識(shí)點(diǎn),寫出來(lái)和大家分享!
---------------------------------------------------------------------------------------------------------------------
聲明:
? ? 此文為原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)保留如下信息
? ? 作者:聶飛(afreez)
? ? 聯(lián)系方式:[email]afreez@sina.com[/email] (歡迎與作者交流)
? ? 初次發(fā)布時(shí)間:2006-06-08
? ? 不經(jīng)本人同意,不得用語(yǔ)商業(yè)或贏利性質(zhì)目的,否則,作者有權(quán)追究相關(guān)責(zé)任!
-----------------------------------------------------------------------------
例子實(shí)現(xiàn)了直接寫屏的功能,即把屏幕清空(變黑),程序的流程大致為:打開一個(gè)FrameBuffer設(shè)備;通過(guò)mmap調(diào)用把顯卡的物理內(nèi)存空間映射到用戶空間;通過(guò)映射關(guān)系直接寫內(nèi)存。
頭文件
fbtools.h
#ifndef _FBTOOLS_H_
#define _FBTOOLS_H_
#include <linux/fb.h>
//a framebuffer device structure;
typedef struct fbdev{
? ? ? ? ? int fb;
? ? ? ? ? unsigned long fb_mem_offset;
? ? ? ? ? unsigned long fb_mem;
? ? ? ? ? struct fb_fix_screeninfo fb_fix;
? ? ? ? ? struct fb_var_screeninfo fb_var;
? ? ? ? ? char dev[20];
} FBDEV, *PFBDEV;
//open & init a frame buffer
//to use this function,
//you must set FBDEV.dev="/dev/fb0"
//or "/dev/fbX"
//it's your frame buffer.
int fb_open(PFBDEV pFbdev);
//close a frame buffer
int fb_close(PFBDEV pFbdev);
//get display depth
int get_display_depth(PFBDEV pFbdev);
//full screen clear
void fb_memset(void *addr, int c, size_t len);
#endif
測(cè)試文件,其中深顏色的注釋部分為在我機(jī)器上測(cè)得的結(jié)果
fbtools.c
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <asm/page.h>
#include "fbtools.h"
#define TRUE ? ? ? 1
#define FALSE ? ? ? 0
#define MAX(x,y) ? ? ((x)>(y)?(x):(y))
#define MIN(x,y) ? ? ((x)<(y)?(x):(y))
//open & init a frame buffer
int fb_open(PFBDEV pFbdev)
{
? ? ? ? ? pFbdev->fb = open(pFbdev->dev, O_RDWR);// pFbdev->fb==3
? ? ? ? ? if(pFbdev->fb < 0)
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("Error opening %s: %m. Check kernel config\n", pFbdev->dev);
? ? ? ? ? ? ? ? ? ? return FALSE;
? ? ? ? ? }
? ? ? ? ? if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("ioctl FBIOGET_VSCREENINFO\n");
? ? ? ? ? ? ? ? ? ? return FALSE;
? ? ? ? ? }
? ? ? ? ? if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("ioctl FBIOGET_FSCREENINFO\n");
? ? ? ? ? ? ? ? ? ? return FALSE;
? ? ? ? ? }
? ? ? ?
? ? ? ? ? //map physics address to virtual address
? ? ? ? ? // pFbdev->fb_fix.smem_start=f0000000
? ? ? ? ? pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
// pFbdev->fb_fix.smem_len=100 0000 pFbdev->fb_mem_offset=0
// pFbdev->fb_mem =0
? ? ? ? ? pFbdev->fb_mem = (unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len +
? ? ? ? ? ? ? ? ? ? ? ? ? ? pFbdev->fb_mem_offset,
? ? ? ? ? ? ? ? ? ? PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0);
? ? ? ? ? if (-1L == (long) pFbdev->fb_mem)
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("mmap error! mem:%d offset:%d\n", pFbdev->fb_mem,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pFbdev->fb_mem_offset);
? ? ? ? ? ? ? ? ? ? return FALSE;
? ? ? ? ? }
? ? ? ?
? ? ? ? ? return TRUE;
}
//close frame buffer
int fb_close(PFBDEV pFbdev)
{
? ? ? ? ? close(pFbdev->fb);
? ? ? ? ? pFbdev->fb=-1;
}
//get display depth
int get_display_depth(PFBDEV pFbdev);
{
? ? ? ? ? if(pFbdev->fb<=0)
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("fb device not open, open it first\n");
? ? ? ? ? ? ? ? ? ? return FALSE;
? ? ? ? ? }
? ? ? ? ? return pFbdev->fb_var.bits_per_pixel;
}
//full screen clear
void fb_memset (void *addr, int c, size_t len)
{
? memset(addr, c, len);
}
//use by test
#define DEBUG
#ifdef DEBUG
main()
{
? ? ? ? ? FBDEV fbdev;
? ? ? ? ? memset(&fbdev, 0, sizeof(FBDEV));
? ? ? ? ? strcpy(fbdev.dev, "/dev/fb0");
? ? ? ? ? if(fb_open(&fbdev)==FALSE)
? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? printf("open frame buffer error\n");
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? }
? ? ? ? ? //注意,下面一行有bug
? ? ? ? ? fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
? ? ? ?
? ? ? ? ? fb_close(&fbdev);
}
#endif
編譯
如果對(duì)上述代碼直接進(jìn)行編譯的話,是不能成功的,即會(huì)出現(xiàn)類似下面的編譯錯(cuò)誤
#gcc –o fbtools fbtools.c
fbtools.c: In function `main`
fbtools.c:89:warning:passing arg 1 of `fb_memset` makes pointer from integer without a cast
對(duì)有問題的fbtools.c中的第89行代碼(即加粗的有注釋的那一行)進(jìn)行如下操作
修改為:
fb_memset((void *)(fbdev.fb_mem+fbdev.fb_mem_offset), 0, fbdev.fb_fix.smem_len);
或者
unsigned long temp;
temp= fbdev.fb_mem+fbdev.fb_mem_offset;
fb_memset((void *)temp, 0, fbdev.fb_fix.smem_len);
可以成功編譯成功
而修改為:
fb_memset((&)(fbdev.fb_mem+fbdev.fb_mem_offset), 0, fbdev.fb_fix.smem_len);
或者
unsigned long temp;
temp= fbdev.fb_mem+fbdev.fb_mem_offset;
fb_memset((&)temp, 0, fbdev.fb_fix.smem_len);
會(huì)輸出:段錯(cuò)誤
分析
函數(shù)原形為:void fb_memset (void *addr, int c, size_t len)
而fbtools.c:89調(diào)用時(shí)傳遞的參數(shù)為:
fb_memset(fbdev.fb_mem+fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
fbdev.fb_mem和fbdev.fb_mem_offset都是unsigned long類型的變量,它們的計(jì)算結(jié)果保存在一個(gè)臨時(shí)的棧空間,傳遞調(diào)用時(shí),其臨時(shí)的地址是不能夠傳遞到被調(diào)用的函數(shù)的,所以編譯是同不過(guò)的。具體的可以參考內(nèi)存分配的相關(guān)知識(shí),記得《effective c++》一書里講的很詳細(xì),可以參考。
至于修改后的:
fb_memset((&)temp, 0, fbdev.fb_fix.smem_len);
編譯出現(xiàn)段錯(cuò)誤,也是很好理解的,因?yàn)?&)temp不等于(void *)temp,也不等于
(void *)(fbdev.fb_mem+fbdev.fb_mem_offset),具體原因讀者可以對(duì)照《effective c++》思考。
轉(zhuǎn)載于:https://blog.51cto.com/afreez/7348
總結(jié)
以上是生活随笔為你收集整理的与afreez一起学习DirectFB之:一个linux下的framebuffer例子的学问的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吉普赛人祖传的神奇读心术:你敢试吗?
- 下一篇: PHP 6:PHP 基本数据类型