1 : 框架结构
2 : 源码浅析
/**
这个函数做了三件事情
1 : 在/proc下创建了文件
2 : 注册了一个字符设备
3 : 在/sys/class下创建了类
*/
static int __init fbmem_init(void)
{
//在/proc目录下创建一个虚拟文件,用户空间可以通过这个文件查看驱动的一些信息
proc_create("fb",0,NULL,&fb_proc_fops);
/**
注册了一个字符设备,主设备号为 29。
次设备号最大为 31, #define FB_MAX (32)
在do_register_framebuffer()函数中,会依据次设备号为索引值将注册的fb_info放到registered_fb[]中.
这点和v4l2子系统中的video_device[]设计的类似
register_framebuffer ( struct fb_info * fb_info )
{
static int do_register_framebuffer(struct fb_info *fb_info)
{
.....
if (num_registered_fb == FB_MAX)
return -ENXIO
num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++)
if (!registered_fb[i])
break;
.....
registered_fb[i] = fb_info;
.....
}
}
向 VFS层提供的操作接口集合 是 fb_fops,
当应用空间调用 read 、ioctl ...时候,那么fb_fops中定义的对应函数会被调用,在这些对应的
函数中 又会调用具体硬件提供的对应函数,这是分层思想的体现吧,
*/
if(register_chrdev(FB_MAJOR,"fb",&fb_fops))
{
printk("unable to get major %d for fb devs\n", FB_MAJOR);
}
/**
在/sys/class目录下创建类
但是在这里并没有创建设备,设备是在register_framebuffer(struct fb_info * fb_info)函数中创建的
register_framebuffer ( struct fb_info * fb_info )
{
do_register_framebuffer( fb_info )
{
......
fb_info->dev = device_create(fb_class, fb_info->device,MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
......
}
}
*/
fb_class = class_create(THIS_MODULE,"graphics");
if(IS_ERR(fb_class))
{
printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
fb_class = NULL;
}
return 0;
}
3 : 实验验证