2. fbdev 核心数据结构:struct fb_info、struct fb_var_screeninfo、struct fb_fix_screeninfo 的详细解析

在 Linux 内核 fbdev 子系统中,三个核心数据结构构成了整个显示框架的基石:struct fb_info 代表一个完整的帧缓冲设备实例,struct fb_var_screeninfo 描述可变显示参数,struct fb_fix_screeninfo 描述固定硬件参数。理解这三者的关系与内部细节,是进行兼容层设计与驱动迁移的前提。

核心概念: fbdev 采用“可变 + 固定”双结构描述显示模式。可变参数(分辨率、位深、时序)可由用户空间动态修改;固定参数(帧缓冲物理地址、内存大小、步长)由硬件决定,驱动初始化后通常不变。

2.1 struct fb_info:帧缓冲设备的核心实例

struct fb_info 是 fbdev 驱动中最重要的数据结构,每个注册的帧缓冲设备对应一个 fb_info 实例。它聚合了设备的所有状态、操作函数指针、底层内存管理和辅助数据。

struct fb_info {
    atomic_t count;                    /* 引用计数 */
    int node;                          /* 设备节点号(/dev/fbN 中的 N) */
    int flags;                         /* 设备标志位 */
    struct mutex lock;                 /* 操作互斥锁 */
    struct mutex mm_lock;              /* 内存映射互斥锁 */
    struct fb_var_screeninfo var;      /* 当前可变参数 */
    struct fb_fix_screeninfo fix;      /* 当前固定参数 */
    struct fb_ops *fbops;              /* 设备操作函数表 */
    struct device *device;             /* 关联的通用设备结构 */
    struct device *dev;                /* 帧缓冲设备自身 */
    int class_flag;                    /* 类标志 */
    struct fb_deferred_io *fbdefio;    /* 延迟 I/O 支持 */
    struct fb_pixmap pixmap;           /* 像素图辅助缓冲区 */
    struct fb_pixmap sprite;           /* 硬件光标辅助缓冲区 */
    struct fb_cursor cursor;           /* 光标状态 */
    struct fb_monspecs monspecs;       /* 显示器规格 */
    struct fb_videomode *mode;         /* 当前视频模式 */
    struct fb_ops *fbops;              /* 操作函数表 */
    char __iomem *screen_base;         /* 帧缓冲虚拟基地址 */
    unsigned long screen_size;         /* 帧缓冲总大小(字节) */
    void *pseudo_palette;              /* 伪调色板 */
    struct fb_ops *fbops;              /* 操作函数表 */
    /* ... 更多辅助字段 */
};
迁移关注点: 在 DRM/KMS 兼容层设计中,fb_info 的 screen_base 和 screen_size 是映射到 DRM GEM 对象的关键桥梁。fbops 中的 fb_open/fb_release/fb_ioctl 需要被兼容层拦截并转发到 DRM 核心。

struct fb_info 核心字段分类表

分类 字段名 说明 兼容层处理策略
设备标识 node 设备节点编号 由 DRM 主设备号映射
显示参数 var 可变参数(分辨率、位深) 从 DRM CRTC/connector 状态转换
硬件参数 fix 固定参数(物理地址、步长) 从 DRM GEM 对象属性填充
操作函数 fbops 驱动操作函数表 兼容层提供统一实现
内存管理 screen_base 帧缓冲虚拟地址 映射 DRM GEM 对象的 vaddr
内存管理 screen_size 帧缓冲总大小 由 GEM 对象大小决定
辅助数据 pseudo_palette 伪调色板(8bpp 模式) 兼容层模拟
struct fb_info 内部结构关系图 struct fb_info var (可变参数) fix (固定参数) fbops (操作表) screen_base (虚拟地址) screen_size (内存大小) pseudo_palette 说明: • var 和 fix 是 fbdev 用户空间接口的核心,通过 FBIOGET_VSCREENINFO / FBIOGET_FSCREENINFO 获取。 • screen_base 在兼容层中映射到 DRM GEM 对象的虚拟地址,screen_size 对应 GEM 对象大小。 • fbops 中的 ioctl 处理函数是兼容层需要重点拦截和重定向的部分。

2.2 struct fb_var_screeninfo:可变显示参数详解

struct fb_var_screeninfo 是用户空间与内核交互最频繁的结构体。它描述了显示模式中可由软件动态调整的参数,包括分辨率、颜色深度、像素时钟、时序参数等。应用程序通过 FBIOGET_VSCREENINFO 和 FBIOPUT_VSCREENINFO ioctl 进行读写。

struct fb_var_screeninfo {
    __u32 xres;                /* 可见水平分辨率(像素) */
    __u32 yres;                /* 可见垂直分辨率(像素) */
    __u32 xres_virtual;        /* 虚拟水平分辨率(像素) */
    __u32 yres_virtual;        /* 虚拟垂直分辨率(像素) */
    __u32 xoffset;             /* 虚拟到可见的水平偏移 */
    __u32 yoffset;             /* 虚拟到可见的垂直偏移 */
    __u32 bits_per_pixel;      /* 每像素位数(bpp) */
    __u32 grayscale;           /* 灰度标志(非零表示灰度) */
    struct fb_bitfield red;    /* 红色通道位域 */
    struct fb_bitfield green;  /* 绿色通道位域 */
    struct fb_bitfield blue;   /* 蓝色通道位域 */
    struct fb_bitfield transp; /* 透明度通道位域 */
    __u32 nonstd;              /* 非标准像素格式标志 */
    __u32 activate;            /* 模式激活标志 */
    __u32 height;              /* 显示器高度(mm) */
    __u32 width;               /* 显示器宽度(mm) */
    __u32 accel_flags;         /* 硬件加速标志(已废弃) */
    __u32 pixclock;            /* 像素时钟(皮秒) */
    __u32 left_margin;         /* 行同步前沿(像素时钟周期数) */
    __u32 right_margin;        /* 行同步后沿(像素时钟周期数) */
    __u32 upper_margin;        /* 帧同步前沿(行数) */
    __u32 lower_margin;        /* 帧同步后沿(行数) */
    __u32 hsync_len;           /* 行同步脉冲长度 */
    __u32 vsync_len;           /* 帧同步脉冲长度 */
    __u32 sync;                /* 同步信号极性标志 */
    __u32 vmode;               /* 视频模式标志 */
    __u32 rotate;              /* 旋转角度 */
    __u32 colorspace;          /* 色彩空间 */
    __u32 reserved[4];         /* 保留字段 */
};

可变参数关键字段分组

分组 字段 典型值示例 兼容层映射目标
分辨率 xres, yres 1920, 1080 DRM connector 的 mode 信息
虚拟分辨率 xres_virtual, yres_virtual 1920, 2160(双缓冲) DRM framebuffer 的宽高
颜色深度 bits_per_pixel 32 DRM 像素格式(如 DRM_FORMAT_XRGB8888)
位域 red, green, blue, transp 偏移 16,8,0;长度 8 DRM 像素格式的位域定义
时序 pixclock, left_margin, right_margin, hsync_len, upper_margin, lower_margin, vsync_len pixclock=14625 DRM display mode 的时序字段
同步极性 sync FB_SYNC_HOR_HIGH_ACT DRM mode 的 flags
旋转 rotate 0, 90, 180, 270 DRM 旋转属性
迁移陷阱: fbdev 的 pixclock 单位是皮秒(picoseconds),而 DRM 的 clock 单位是 kHz。转换公式为:clock_khz = 1000000000 / pixclock_ps。位域结构 fb_bitfield 的 offset 和 length 需要精确映射到 DRM 四字符码(FourCC)格式的位布局。
fb_var_screeninfo 字段分组与 DRM 映射关系 分辨率组 xres, yres 虚拟分辨率组 xres_virtual, yres_virtual 颜色深度组 bits_per_pixel, 位域 时序组 pixclock, margin, sync DRM connector mode hdisplay, vdisplay DRM framebuffer width, height DRM FourCC 格式 DRM_FORMAT_XRGB8888 DRM display mode clock, hsync_start, ... 关键映射规则: 1. 分辨率组直接映射到 DRM connector 的 drm_display_mode 中的 hdisplay / vdisplay。 2. 虚拟分辨率决定 DRM framebuffer 的创建尺寸,xoffset/yoffset 对应 page flip 时的偏移。 3. 位域结构 (red/green/blue/transp) 必须转换为 DRM 四字符码,例如 offset=16,8,0 且 length=8 对应 XRGB8888。 4. pixclock 从皮秒转换为 kHz:clock_khz = 1000000000 / pixclock_ps。

2.3 struct fb_fix_screeninfo:固定硬件参数详解

struct fb_fix_screeninfo 描述帧缓冲设备的固定硬件特性,这些参数在驱动初始化时确定,用户空间只能读取(通过 FBIOGET_FSCREENINFO),不能修改。它提供了帧缓冲内存的物理布局信息。

struct fb_fix_screeninfo {
    char id[16];               /* 设备标识字符串(如 "radeonfb") */
    unsigned long smem_start;  /* 帧缓冲物理起始地址 */
    __u32 smem_len;            /* 帧缓冲总长度(字节) */
    __u32 type;                /* 显示类型(如 FB_TYPE_PACKED_PIXELS) */
    __u32 type_aux;            /* 辅助类型(用于 interleaved 格式) */
    __u32 visual;              /* 颜色视觉类型(如 FB_VISUAL_TRUECOLOR) */
    __u16 xpanstep;            /* 水平 pan 步长(像素) */
    __u16 ypanstep;            /* 垂直 pan 步长(像素) */
    __u16 ywrapstep;           /* 垂直 wrap 步长(像素) */
    __u32 line_length;         /* 一行像素的字节数(步长) */
    unsigned long mmio_start;  /* 内存映射 I/O 物理起始地址 */
    __u32 mmio_len;            /* 内存映射 I/O 长度(字节) */
    __u32 accel;               /* 硬件加速类型 */
    __u16 capabilities;        /* 设备能力标志 */
    __u16 reserved[2];         /* 保留字段 */
};

固定参数关键字段详解

字段 含义 典型值 兼容层实现方式
id 设备标识字符串 "drmfb" 固定为 "drmfb" 或驱动名称
smem_start 帧缓冲物理地址 0x10000000 从 DRM GEM 对象的物理地址获取(可能为 0 如果不可用)
smem_len 帧缓冲总大小 8294400 (1920×1080×4) DRM GEM 对象大小
type 显示类型 FB_TYPE_PACKED_PIXELS 固定为 PACKED_PIXELS
visual 颜色视觉类型 FB_VISUAL_TRUECOLOR 根据 DRM 像素格式确定
line_length 行步长(字节) 7680 (1920×4) DRM framebuffer 的 pitch
mmio_start MMIO 物理地址 0x10010000 从 DRM 设备获取(可能为 0)
mmio_len MMIO 区域长度 65536 从 DRM 设备获取
兼容层实现要点: smem_start 在兼容层中通常返回 0 或一个占位地址,因为 DRM 的 GEM 对象物理地址可能不连续或不可直接暴露给用户空间。用户空间应通过 mmap 操作获取虚拟地址,而非直接使用物理地址。line_length 必须与 DRM framebuffer 的 pitch 严格一致,否则会导致显示错位。
fb_fix_screeninfo 内存布局与 DRM 映射 帧缓冲内存 (smem) 物理地址: smem_start 总大小: smem_len 行步长: line_length MMIO 区域 物理地址: mmio_start 区域长度: mmio_len 用于硬件控制寄存器 DRM GEM 对象 size = smem_len, pitch = line_length DRM 设备 MMIO 通过 DRM ioctl 查询 注意:smem_start 在兼容层中通常返回 0,因为 DRM 不保证物理地址连续或可访问。 用户空间应通过 mmap 操作 /dev/fbN 获取虚拟地址,而非直接使用 smem_start。

2.4 三结构体协作关系总结

三个核心数据结构在 fbdev 驱动中协同工作,形成完整的显示设备描述模型:

  • struct fb_info:设备实例的“总控中心”,包含 var 和 fix 作为子结构,以及操作函数表 fbops 和内存管理字段。
  • struct fb_var_screeninfo:描述“软件可调”的显示模式参数,是用户空间配置显示的核心接口。
  • struct fb_fix_screeninfo:描述“硬件固定”的内存布局参数,提供帧缓冲的物理描述。
兼容层设计核心原则: 在 DRM/KMS 兼容层中,fb_info 作为“代理对象”存在,其 var 和 fix 字段的值从 DRM 核心状态动态转换而来,而非直接对应硬件寄存器。fbops 中的 ioctl 处理函数需要拦截 fbdev 特有的命令(如 FBIOPUT_VSCREENINFO),将其转换为 DRM 的 mode set 和 framebuffer 操作序列。
三结构体协作关系 struct fb_info