1. 初始化帧缓冲设备
任务说明
编写一个Linux内核模块,完成帧缓冲设备的注册,并实现最基本的open/release文件操作。模块加载时动态分配帧缓冲设备,卸载时正确释放。通过/dev/fb*设备节点验证模块是否注册成功。
环境依赖
- Linux内核源码树(版本需与运行内核一致),路径如
/lib/modules/$(uname -r)/build - 内核配置开启
CONFIG_FB支持 - 具备root权限用于模块加载与设备节点操作
完整代码
// fb_init.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fb.h>
#include <linux/platform_device>
#include <linux/uaccess.h>
static struct fb_info *fb_info;
static struct fb_fix_screeninfo fix_info = {
.id = "myfb",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR,
.line_length = 1024 * 4,
.smem_len = 1024 * 768 * 4,
};
static int myfb_open(struct fb_info *info, int user)
{
pr_info("myfb: open (user=%d)\n", user);
return 0;
}
static int myfb_release(struct fb_info *info, int user)
{
pr_info("myfb: release (user=%d)\n", user);
return 0;
}
static struct fb_ops myfb_ops = {
.owner = THIS_MODULE,
.fb_open = myfb_open,
.fb_release = myfb_release,
// 其余操作由fbdev核心提供默认实现
};
static int __init myfb_init(void)
{
fb_info = framebuffer_alloc(0, NULL);
if (!fb_info)
return -ENOMEM;
fb_info->fix = fix_info;
fb_info->var.xres = 1024;
fb_info->var.yres = 768;
fb_info->var.bits_per_pixel = 32;
fb_info->fbops = &myfb_ops;
fb_info->screen_base = NULL; // 无真实显存,仅注册设备
if (register_framebuffer(fb_info) < 0) {
framebuffer_release(fb_info);
return -EINVAL;
}
pr_info("myfb: registered as /dev/fb%d\n", fb_info->node);
return 0;
}
static void __exit myfb_exit(void)
{
if (fb_info) {
unregister_framebuffer(fb_info);
framebuffer_release(fb_info);
pr_info("myfb: unregistered\n");
}
}
module_init(myfb_init);
module_exit(myfb_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Minimal framebuffer device with open/release");
Makefile
obj-m := fb_init.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
编译与加载
make
sudo insmod fb_init.ko
dmesg | tail -5 # 应看到 "myfb: registered as /dev/fbN"
ls -l /dev/fb* # 确认新设备节点存在
验证方法
- 注册验证:加载模块后执行
cat /proc/fb,输出中应包含0 myfb(或对应编号)。 - open/release验证:执行
sudo cat /dev/fbN(N为实际编号),该操作会触发内核的open调用;随后用dmesg | tail查看,应依次出现myfb: open (user=1)和myfb: release (user=1)两条日志。由于未分配真实显存,cat读取可能返回错误,这属于预期行为——本案例仅验证设备注册与open/release回调被正确调用。 - 卸载验证:
sudo rmmod fb_init后再次执行cat /proc/fb,确认myfb条目消失。
常见问题
- 注册失败(register_framebuffer返回负值):检查内核是否支持
CONFIG_FB,以及系统是否已有帧缓冲设备占用编号。可尝试在myfb_init中指定fb_info->node = -1让内核自动分配。 - insmod报错“Invalid module format”:确认Makefile中的KDIR指向的内核源码树与当前运行内核版本完全一致。
- open回调未被调用:某些用户态程序(如
cat)可能因设备无显存而提前失败。可用sudo dd if=/dev/fbN of=/dev/null bs=1 count=1触发open,或编写简单的C程序调用open()后立即close()来验证。