linux下的GUI系统的基础,x server是一个用户态的程序。
他的功能,主要体现在两个方面。
1. 获取键盘、鼠标等输入设备的输入。并将这类信息通知给应用程序。
2. 接收应用程序的绘图请求,实施具体的绘图操作。
下面分别分析这两方面功能的实现:
一、获取键盘、鼠标等输入设备的输入
过程大致如下:
a)内核态
用户按键盘或移动鼠标
键盘或鼠标的驱动程序,在其中断处理程序中,调用input_event函数对输入事件进行处理。
然后,input_event函数在其结尾处,调用如下代码,将输入事件同步到 /dev/input/event0 之类的文件。
handle->handler->event(handle, type, code, value);
b)用户态
用户态程序,通过C库函数open,打开 /dev/input/event0 之类的文件得到相应的文件描述符fd,通过select轮询fd是否有数据可读。
一旦有数据可读,通过C库函数read读取fd,即可获得键盘或鼠标的输入信息。
下面的网页,提供了一个代码示例。
http://blog.csdn.net/lanmanck/article/details/8423669
二、绘图
x server是通过frame buffer机制进行绘图的。
由于x server是标准的用户态程序。因此,他所用的frame buffer绘图机制,对于我们一般的应用程序也是可用的。
下面的网页,演示了frame buffer使用方法。
http://bbs.chinaunix.net/thread-3637722-1-1.html
另外,下面的描述对于理解frame buffer很有帮助。
摘自:http://www.oschina.net/question/565065_113477
linux中Framebuffer的原理及实现机制
*一、FrameBuffer的原理*
FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。
Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出 FrameBuffer这 个设备来供用户态进程实现直接写屏。Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过Framebuffer的读写直接对显存进行操 作。用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。 这种操 作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。
但Framebuffer本身不具备任何运算数据的能力,就只好比是一个暂时存放水的水池.CPU将运算后的结果放到这个水池,水池再将结果流到显示器. 中间不会对数据做处理. 应用程序也可以直接读写这个水池的内容.在这种机制下,尽管Framebuffer需要真正的显卡驱动的支持,但所有显示任务都有CPU完成,因此CPU 负担很重.
framebuffer的设备文件一般是 /dev/fb0、/dev/fb1 等等。
可以用命令: #dd if=/dev/zero of=/dev/fb 清空屏幕.
如果显示模式是 1024×768-8 位色,用命令:$ dd if=/dev/zero of=/dev/fb0 bs=1024 count=768 清空屏幕;
用命令: #dd if=/dev/fb of=fbfile 可以将fb中的内容保存下来;
可以重新写回屏幕: #dd if=fbfile of=/dev/fb;
在使用Framebuffer时,Linux是将显卡置于图形模式下的.
在应用程序中,一般通过将 FrameBuffer 设备映射到进程地址空间的方式使用,比如下面的程序就打开 /dev/fb0 设备,并通过mmap 系统调用进行地址映射,随后用 memset 将屏幕清空(这里假设显示模式是 1024×768-8 位色模式,线性内存模式):
int fb;
unsigned char* fb_mem;
fb = open (“/dev/fb0″, O_RDWR);
fb_mem = mmap (NULL, 1024*768, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
memset (fb_mem, 0, 1024*768 );
FrameBuffer 设备还提供了若干ioctl命令,通过这些命令,可以获得显示设备的一些固定信息(比如显示内存大小)、与显示模式相关的可变信息(比如分辨率、象素结构、每扫描线的字节宽度),以及伪彩 色模式下的调色板信息等等。
通过 FrameBuffer设备,还可以获得当前内核所支持的加速显示卡的类型(通过固定信息得到),这种类型通常是和特定显示芯片相关的。比如目前最新的内核(2.4.9)中,就包含有 对S3、Matrox、nVidia、3Dfx 等等流行显示芯片的加速支持。在获得了加速芯片类型之后,应用程序就可以将 PCI设备的内存I/O(memio)映射到进程的地址空间。这些memio
一般是用来控制显示卡的寄存器,通过对这些寄存器的操作,应用程序就可以控制特定显卡的加速功能。
PCI设备可以将自己的控制寄存器映射到物理内存空间,而后,对这些控制寄存器的访问,给变成了对物理内存的访问。因此,这些寄存器又被称 为”memio”。一旦被映 射到物理内存,Linux的普通进程就可以通过 mmap 将这些内存 I/O 映射到进程地址空间,这样就可以直接访问这些寄存器了。
当然,因为不同的显示芯片具有不同的加速能力,对memio的使用和定义也各自不同,这时,就需要针对加速芯片的不同类型来编写实现不同的加速功能。比如 大多数芯片都提供了对矩形填充的硬件加速支持,但不同的芯片实现方 式不同,这时,就需要针对不同的芯片类型编写不同的用来完成填充矩形的函数。
FrameBuffer 只是一个提供显示内存和显示芯片寄存器从物理内存映射到进程地址空间中的设备。所以,对于应用程序而言,如果希望在FrameBuffer 之上进行图形编程,还需要自己动手完成其他许多工作。