1. FrameBuffer 基础概念

1.1 什么是 FrameBuffer

FrameBuffer(帧缓冲)是 Linux 内核提供的一种抽象显示设备接口。它将显存映射到用户空间,应用程序可以直接向这块内存写入像素数据,无需关心底层显示硬件的具体实现。简单来说,FrameBuffer 就是一块“画布”,CPU 或 GPU 在上面绘制图像,显示控制器则定时扫描这块画布的内容并输出到显示器。

核心定义:FrameBuffer 是位于系统主存或专用显存中的一块连续内存区域,存储了屏幕每个像素的颜色值。Linux 通过 /dev/fb0 设备文件暴露给用户空间,应用程序使用 mmap() 系统调用将其映射到进程地址空间,直接读写像素数据。
概念 说明
像素数据 每个像素由若干字节表示,常见格式有 RGB565(16位)、RGB888(24位)、ARGB8888(32位)
显存地址 FrameBuffer 的物理地址由显示控制器固定映射,通过 mmap() 映射到用户虚拟地址空间
刷新机制 显示控制器以固定帧率(如 60Hz)从 FrameBuffer 读取数据,逐行扫描输出到显示器
设备节点 /dev/fb0 是第一个帧缓冲设备,/dev/fb1 对应第二个,以此类推
FrameBuffer 数据流与显示过程 用户应用程序 (GUI / 游戏 / 视频播放) mmap() FrameBuffer 驱动 (fb_ops / fbmem.c) DMA / 内存映射 物理显存 (系统主存 / 专用VRAM) 显示控制器 (LCDC / HDMI TX) 定时扫描 显示器 (LCD / HDMI 屏幕) 视频信号 关键路径说明: 1. 应用程序通过 mmap() 映射 /dev/fb0 到用户空间 2. 直接写入像素数据到映射内存区域 3. 显示控制器以固定帧率扫描显存,输出到显示器

1.2 帧缓冲在 Linux 图形栈中的位置

Linux 图形栈从底层到上层分为多个层次,FrameBuffer 位于内核空间,是显示输出的最底层接口之一。理解它的位置有助于把握整个图形系统的数据流向。

层次 组件 说明
用户空间应用 Qt / GTK / SDL / Wayland 客户端 图形界面程序,通过 EGL / DRM / fbdev 接口绘制
显示服务器 Xorg / Wayland (Weston / KWin) 管理窗口合成、输入事件分发,输出合成后的帧
图形库 Mesa / EGL / OpenGL ES / Vulkan 提供硬件加速渲染 API,生成像素数据
内核 DRM/KMS Direct Rendering Manager + Kernel Mode Setting 现代 Linux 显示核心,管理显存、模式设置、VSync
FrameBuffer 层 fbmem.c + fb_ops 驱动回调 传统帧缓冲接口,提供 /dev/fb0 设备节点
硬件层 LCD 控制器 / HDMI TX / VGA DAC 物理显示接口,将数字信号转换为模拟/数字视频信号
注意:在嵌入式 Linux 系统中,FrameBuffer 仍然是主流显示接口,尤其在没有 GPU 或 DRM 支持的平台上。而在桌面 Linux 中,DRM/KMS 已逐步取代传统 FrameBuffer,但 /dev/fb0 作为兼容接口仍然存在。
Linux 图形栈层次结构 用户空间应用 (Qt / GTK / SDL / Wayland 客户端) 显示服务器 (Xorg / Wayland Weston / KWin) 图形库 (Mesa / EGL / OpenGL ES / Vulkan) 内核 DRM/KMS (Direct Rendering Manager) FrameBuffer 层 (fbmem.c + fb_ops 驱动回调) 硬件层 (LCD 控制器 / HDMI TX / VGA DAC) 用户空间 应用程序 显示服务器 图形库 内核空间

1.3 FrameBuffer 与 VGA/HDMI 的关系

FrameBuffer 是内存中的像素数据缓冲区,而 VGA 和 HDMI 是物理传输接口标准。两者之间的关系可以概括为:FrameBuffer 提供“内容”,VGA/HDMI 提供“通道”。

  • VGA(Video Graphics Array):模拟视频接口,传输 RGB 模拟信号 + 行场同步信号。显示控制器将 FrameBuffer 中的数字像素值通过 DAC(数模转换器)转换为模拟电压,经 VGA 线缆传输到显示器。
  • HDMI(High-Definition Multimedia Interface):数字视频/音频接口,传输 TMDS 差分信号。显示控制器将 FrameBuffer 中的数字像素值直接打包为 TMDS 数据包,通过 HDMI 线缆传输,无需 DAC 转换。
  • 共同点:无论使用哪种物理接口,显示控制器都从同一个 FrameBuffer 内存区域读取像素数据。驱动只需配置好显存地址和时序参数,硬件自动完成扫描输出。
特性 VGA HDMI FrameBuffer 角色
信号类型 模拟(RGB + 同步) 数字(TMDS 差分) 提供数字像素源
是否需要 DAC 是(数字→模拟) 否(直接数字传输) FrameBuffer 始终为数字格式
最大分辨率 2048×1536(受限于模拟带宽) 4096×2160(HDMI 2.0) 由显存大小和控制器能力决定
音频传输 不支持 支持(内嵌音频流) FrameBuffer 仅处理视频像素
驱动配置 设置时序、DAC 参考电压 设置时序、TMDS 时钟、EDID 解析 统一通过 fb_var_screeninfo 配置
常见误区:FrameBuffer 不等于 VGA 或 HDMI。FrameBuffer 是软件层面的内存缓冲区,VGA/HDMI 是硬件物理接口。同一个 FrameBuffer 驱动可以同时支持 VGA 和 HDMI 输出,只需在硬件初始化时配置不同的显示控制器寄存器。例如,许多嵌入式 SoC 的 LCDC 控制器可以同时驱动 VGA DAC 和 HDMI PHY。
FrameBuffer 与 VGA / HDMI 的硬件连接关系 FrameBuffer 显存 (RGB888 像素数据) 地址: 0x9E00_0000 显示控制器 (LCDC / Display Engine) DMA 读取 + 时序生成 DMA VGA DAC (ADV7123 / 模拟输出) HDMI PHY (TMDS 编码 / 数字输出) RGB 数字总线 RGB + 控制信号 VGA 显示器 HDMI 显示器 模拟 RGB TMDS

1.4 FrameBuffer 驱动核心数据结构

Linux 内核中,FrameBuffer 驱动围绕 struct fb_info 和 struct fb_ops 两个核心结构体展开。理解这些数据结构是编写 FrameBuffer 驱动的基础。

/* 核心结构体:fb_info */
struct fb_info {
    struct fb_var_screeninfo var;   /* 可变参数:分辨率、位深、时序 */
    struct fb_fix_screeninfo fix;   /* 固定参数:显存地址、行长度 */
    struct fb_ops *fbops;           /* 驱动操作函数指针 */
    struct device *device;          /* 关联的设备 */
    char __iomem *screen_base;      /* 显存虚拟地址基址 */
    unsigned long screen_size;      /* 显存大小(字节) */
    void *par;                      /* 驱动私有数据 */
};

/* 可变参数结构体:应用层可修改 */
struct fb_var_screeninfo {
    __u32 xres;           /* 可见分辨率:宽度(像素) */
    __u32 yres;           /* 可见分辨率:高度(像素) */
    __u32 bits_per_pixel; /* 每像素位数:16/24/32 */
    __u32 pixclock;       /* 像素时钟(皮秒) */
    __u32 left_margin;    /* 行同步后沿 */
    __u32 right_margin;   /* 行同步前沿 */
    __u32 upper_margin;   /* 场同步后沿 */
    __u32 lower_margin;   /* 场同步前沿 */
    __u32 hsync_len;      /* 行同步脉冲宽度 */
    __u32 vsync_len;      /* 场同步脉冲宽度 */
};

/* 固定参数结构体:驱动初始化时设定,应用层只读 */
struct fb_fix_screeninfo {
    char id[16];          /* 驱动名称标识 */
    unsigned long smem_start;  /* 显存物理地址 */
    __u32 smem_len;       /* 显存长度 */
    __u32 line_length;    /* 一行像素占用的字节数 */
    __u32 visual;         /* 颜色模式:真彩/伪彩/灰度 */
};
关键字段说明:
  • screen_base:驱动通过 ioremap() 或 dma_alloc_coherent() 映射的虚拟地址,应用程序 mmap() 时最终映射到该地址。
  • line_length:等于 xres * bits_per_pixel / 8,通常需要对齐到 4 字节或 16 字节边界。
  • pixclock:决定刷新率,refresh = 1 / (pixclock * (xres+hmargin) * (yres+vmargin))。

1.5 本章小结

  • FrameBuffer 是 Linux 内核提供的显存抽象接口,通过 /dev/fb0 暴露给用户空间。
  • 在 Linux 图形栈中,FrameBuffer 位于内核空间,位于 DRM/KMS 之下、硬件层之上。
  • FrameBuffer 提供像素数据内容,VGA/HDMI 提供物理传输通道,两者通过显示控制器桥接。
  • 驱动核心数据结构为 struct fb_info,包含可变参数(分辨率、时序)和固定参数(显存地址、行长度)。