1. 初始化Framebuffer设备
任务目标
本案例实现Linux下LCD Framebuffer设备的最小初始化流程:打开设备文件、获取屏幕固定与可变参数、计算缓冲区大小并完成内存映射。初始化成功后,向映射内存写入一个像素值,用于验证写入路径可用。
环境与依赖
- Linux系统,内核已启用
CONFIG_FB_DEVICE(标准内核默认开启) - LCD设备节点:
/dev/fb0(若为其他编号,修改代码中的设备路径) - 当前用户需有设备读写权限(可加入
video组或使用sudo运行) - 编译依赖:仅需标准C库与Linux内核头文件(
linux/fb.h、sys/mman.h)
完整代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
int main(void) {
const char *fb_path = "/dev/fb0";
int fd = open(fb_path, O_RDWR);
if (fd < 0) {
perror("open /dev/fb0");
return 1;
}
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
perror("ioctl FBIOGET_FSCREENINFO");
close(fd);
return 1;
}
if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
perror("ioctl FBIOGET_VSCREENINFO");
close(fd);
return 1;
}
printf("分辨率: %ux%u\n", vinfo.xres, vinfo.yres);
printf("色深: %u bpp\n", vinfo.bits_per_pixel);
printf("行字节数: %u\n", finfo.line_length);
printf("屏幕总字节数: %u\n", finfo.smem_len);
/* 计算一帧所需字节数(行字节数 × 行数) */
size_t frame_size = finfo.line_length * vinfo.yres;
if (frame_size > finfo.smem_len) {
fprintf(stderr, "错误: 计算帧大小超过显存大小\n");
close(fd);
return 1;
}
/* 映射显存到用户空间 */
void *fbp = mmap(NULL, frame_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (fbp == MAP_FAILED) {
perror("mmap");
close(fd);
return 1;
}
/* 写入一个像素(假设32bpp,ARGB8888格式,坐标(0,0)为红色) */
if (vinfo.bits_per_pixel == 32) {
unsigned int *pixel = (unsigned int *)fbp;
*pixel = 0x00FF0000; /* 不透明红色 */
printf("已向(0,0)写入红色像素\n");
} else {
printf("当前色深非32bpp,跳过像素写入(仅完成初始化)\n");
}
/* 清理:解除映射并关闭设备 */
munmap(fbp, frame_size);
close(fd);
printf("Framebuffer初始化完成并已清理\n");
return 0;
}
编译与运行
# 编译
gcc -o fb_init fb_init.c
# 运行(若权限不足,加sudo)
./fb_init
验证方法
- 正常输出:程序依次打印分辨率、色深、行字节数、屏幕总字节数,最后显示“Framebuffer初始化完成并已清理”。
- 像素写入验证:若色深为32bpp,程序会向(0,0)写入红色像素。可在运行后观察屏幕左上角是否出现红色点(若LCD当前显示该Framebuffer内容)。
- 错误排查:若打开设备失败,检查
/dev/fb0是否存在及权限;若ioctl失败,确认内核Framebuffer驱动已加载(ls /dev/fb*应有节点)。 - 内存映射检查:程序正常结束且无
mmap错误,说明映射成功;munmap后无崩溃即清理正确。
关键说明
- 代码使用
finfo.line_length * vinfo.yres计算映射大小,而非直接使用finfo.smem_len,因为显存可能大于单帧所需空间(如支持双缓冲)。 - 像素写入仅针对32bpp格式做了演示;若实际屏幕为16bpp或24bpp,需按对应格式构造像素值,本案例聚焦初始化流程,不展开各色深写入。
- 本程序为一次性初始化验证,未实现持续显示或绘制功能;如需在屏幕上绘制图形,应在
munmap前操作fbp指向的内存。