3. 填充单色背景
任务目标
本案例实现Linux Framebuffer驱动的单色背景填充:将整个屏幕填充为指定颜色(如红色),以此验证Framebuffer的mmap映射与像素写入功能是否正常。
环境与依赖
- Linux系统(含/dev/fb0设备节点,需有读写权限)
- 内核已启用Framebuffer驱动(如DRM或simplefb)
- gcc编译器
核心实现
#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(int argc, char *argv[]) {
int fb_fd;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
char *fbp;
long screensize;
unsigned int color = 0x00FF0000; // 默认红色 (ARGB8888)
// 解析命令行参数:可指定颜色值(十六进制,如 0x00FF0000)
if (argc > 1) {
color = (unsigned int)strtoul(argv[1], NULL, 0);
}
// 打开Framebuffer设备
fb_fd = open("/dev/fb0", O_RDWR);
if (fb_fd == -1) {
perror("打开 /dev/fb0 失败");
return 1;
}
// 获取屏幕可变信息(分辨率、位深等)
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
perror("获取可变屏幕信息失败");
close(fb_fd);
return 1;
}
// 获取固定信息(smem_len表示显存大小)
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
perror("获取固定屏幕信息失败");
close(fb_fd);
return 1;
}
// 计算显存总大小(字节)
screensize = finfo.smem_len;
// 将显存映射到用户空间
fbp = (char *)mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
if (fbp == MAP_FAILED) {
perror("mmap 失败");
close(fb_fd);
return 1;
}
// 计算每像素字节数
int bytes_per_pixel = vinfo.bits_per_pixel / 8;
// 将颜色值转换为与当前像素格式匹配的存储值
// 此处假设ARGB8888格式(32位),若实际格式不同需调整
unsigned int pixel_value = color;
// 填充整个屏幕
for (int y = 0; y < vinfo.yres; y++) {
for (int x = 0; x < vinfo.xres; x++) {
long offset = (x + vinfo.xoffset) * bytes_per_pixel +
(y + vinfo.yoffset) * finfo.line_length;
// 按每像素字节数写入
for (int b = 0; b < bytes_per_pixel; b++) {
fbp[offset + b] = (pixel_value >> (b * 8)) & 0xFF;
}
}
}
// 清理资源
munmap(fbp, screensize);
close(fb_fd);
printf("屏幕填充完成:分辨率 %dx%d,颜色 0x%08X\n",
vinfo.xres, vinfo.yres, color);
return 0;
}
编译与运行
# 编译
gcc -o fill_screen fill_screen.c
# 运行(默认填充红色)
./fill_screen
# 指定颜色填充(例如绿色 0x00FF00)
./fill_screen 0x0000FF00
验证方法
- 运行程序后,屏幕应整体变为指定颜色(默认红色),无条纹或花屏现象。
- 若屏幕无变化,检查:
- 当前终端是否处于图形界面(需在纯文本终端或关闭X服务后测试)
- 设备节点权限:
ls -l /dev/fb0,必要时chmod 666 /dev/fb0 - 像素格式是否匹配:程序默认按ARGB8888处理,若实际为RGB565(16位),需修改写入逻辑
- 可通过
fbset命令查看当前分辨率与位深,确认与程序读取的参数一致。
常见问题
- 屏幕无变化:确认没有X Server占用Framebuffer,可切换到tty终端(Ctrl+Alt+F1~F6)测试。
- 颜色显示不正确:不同屏幕的像素格式不同(RGB565、ARGB8888等),需根据
vinfo.bits_per_pixel和vinfo.red/green/blue偏移量调整颜色值转换逻辑。 - mmap失败:确认设备节点存在且当前用户有读写权限。