歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux幀緩沖(Framebuffer)

Linux幀緩沖(Framebuffer)

日期:2017/2/28 15:58:54   编辑:Linux教程

幀緩沖(framebuffer)是Linux為顯示設備提供的一個接口,把顯存抽象後的一種設備,他允許上層應用程序在圖形模式下直接對顯示緩沖區進行讀寫操作。這種操作是抽象的,統一的。用戶不必關心物理顯存的位置、換頁機制等等具體細節。這些都是由Framebuffer設備驅動來完成的。

幀緩沖驅動的應用廣泛,在linux的桌面系統中,Xwindow服務器就是利用幀緩沖進行窗口的繪制。尤其是通過幀緩沖可顯示漢字點陣,成為Linux漢化的唯一可行方案。

Linux FrameBuffer 本質上只是提供了對圖形設備的硬件抽象,在開發者看來,FrameBuffer 是一塊顯示緩存,往顯示緩存中寫入特定格式的數據就意味著向屏幕輸出內容。所以說FrameBuffer就是一塊白板。例如對於初始化為16 位色的FrameBuffer 來說, FrameBuffer中的兩個字節代表屏幕上一個點,從上到下,從左至右,屏幕位置與內存地址是順序的線性關系。

幀緩存可以在系統存儲器(內存)的任意位置,視頻控制器通過訪問幀緩存來刷新屏幕。 幀緩存也叫刷新緩存 Frame buffer 或 refresh buffer, 這裡的幀(frame)是指整個屏幕范圍。

幀緩存有個地址,是在內存裡。我們通過不停的向frame buffer中寫入數據, 顯示控制器就自動的從frame buffer中取數據並顯示出來。全部的圖形都共享內存中同一個幀緩存。

CPU指定顯示控制器工作,則顯示控制器根據CPU的控制到指定的地方去取數據 和 指令, 目前的數據一般是從顯存裡取,如果顯存裡存不下,則從內存裡取, 內存也放不下,則從硬盤裡取,當然也不是內存放不下,而是為了節省內存的話,可以放在硬盤裡,然後通過指令控制顯示控制器去取。幀緩存 Frame Buffer,裡面存儲的東西是一幀一幀的, 顯卡會不停的刷新Frame Buffer, 這每一幀如果不捕獲的話, 則會被丟棄,也就是說是實時的。這每一幀不管是保存在內存還是顯存裡,都是一個顯性的信息,這每一幀假設是800x600的分辨率, 則保存的是800x600個像素點,和顏色值。

幀緩沖設備對應的設備文件為/dev/fb*,如果系統有多個顯示卡,Linux下還可支持多個幀緩沖設備,最多可達32 個,分別為/dev/fb0到/dev/fb31,而/dev/fb則為當前缺省的幀緩沖設備,通常指向/dev/fb0。當然在嵌入式系統中支持一個顯示設備就夠了。幀緩沖設備為標准字符設備,主設備號為29,次設備號則從0到31。分別對應/dev/fb0-/dev/fb31。通過/dev/fb,應用程序的操作主要有這幾種:

1. 讀/寫(read/write)/dev/fb:相當於讀/寫屏幕緩沖區。例如用 cp /dev/fb0 tmp命令可將當前屏幕的內容拷貝到一個文件中,而命令cp tmp > /dev/fb0 則將圖形文件tmp顯示在屏幕上。

2.映射(map)操作:由於Linux工作在保護模式,每個應用程序都有自己的虛擬地址空間,在應用程序中是不能直接訪問物理緩沖區地址的。為此, Linux在文件操作 file_operations結構中提供了mmap函數,可將文件的內容映射到用戶空間。對於幀緩沖設備,則可通過映射操作,可將屏幕緩沖區的物理地址映射到用戶空間的一段虛擬地址中,之後用戶就可以通過讀寫這段虛擬地址訪問屏幕緩沖區,在屏幕上繪圖了。實際上,使用幀緩沖設備的應用程序都是通過映射操作來顯示圖形的。由於映射操作都是由內核來完成,下面我們將看到,幀緩沖驅動留給開發人員的工作並不多。

3. I/O控制:對於幀緩沖設備,對設備文件的ioctl操作可讀取/設置顯示設備及屏幕的參數,如分辨率,顯示顏色數,屏幕大小等等。ioctl的操作是由底層的驅動程序來完成的。

在應用程序中,操作/dev/fb的一般步驟如下:

1. 打開/dev/fb設備文件。

2.用ioctrl操作取得當前顯示屏幕的參數,如屏幕分辨率,每個像素點的比特數。根據屏幕參數可計算屏幕緩沖區的大小。

3. 將屏幕緩沖區映射到用戶空間。

4.映射後就可以直接讀寫屏幕緩沖區,進行繪圖和圖片顯示了。

典型程序段如下:

#include

int main()

{

int fbfd = 0;

struct fb_var_screeninfo vinfo;

struct fb_fix_screeninfo finfo;

long int screensize = 0;

fbfd = open("/dev/fb0", O_RDWR);

ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo);

ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);

screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

fbp=(char*)mmap(0,screensize,PROT_READ|PROT_WRITE,MAP_SHARED, fbfd, 0);

}

Copyright © Linux教程網 All Rights Reserved