android2.3.4----2.关于framebuffer

本文详细解析了Linux系统中Framebuffer的注册流程,包括初始化、内存分配、设备节点创建等步骤,并介绍了上层如何通过文件操作接口与Framebuffer进行交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.framebuffer的初始化
1. 以s3cfb的注册过程说明
module_init(s3cfb_init);
–> platform_driver_register(&s3cfb_driver);
–> s3cfb_probe(struct platform_device *pdev)
在drivers/video/samsung/s3cfb.c中
static int __init s3cfb_probe(struct platform_device *pdev)
{
//第一步为framebuffer分配空间
struct fb_info *fbinfo = framebuffer_alloc(sizeof(s3cfb_info_t), &pdev->dev);
//第二步初始化fbinfo
….
….
//第三步注册framebuffer
ret = register_framebuffer(&s3cfb_info[index].fb);
}
2. framebuffer_alloc过程
在drivers/video/fbsysfs.c中,
主要作用就是: 申请内存,并略微初始化fb_info结构体,主要的初始化是在s3c_probe函数中
struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
{
int fb_info_size = sizeof(struct fb_info);
struct fb_info *info;
fb_info_size += PADDING; //为了对齐
//申请内存,并清零
info = (struct fb_info *) kzalloc(fb_info_size + size, GFP_KERNEL);
info->par = p + fb_info_size;
//device指针保存dev
info->device = dev;
return info;
}
3. register_framebuffer过程
在drivers/video/fbmem.c中
主要作用是:
1. 在全局变量数组registered_fb中查找未使用的一项,把找到的这个项号保存在fb_info中
2. 在/dev/graphics/fb目录下创建设备结点, /dev/graphics/fb0 ls /dev/graphics/fb1就产生了
3. 将fb_info添加到全局数组registered_fb中,并发送msg,说明注册完成
int register_framebuffer(struct fb_info *fb_info)
{
int i;
struct fb_event event;
struct fb_videomode mode;

if (num_registered_fb == FB_MAX)
    return -ENXIO;

if (fb_check_foreignness(fb_info))
    return -ENOSYS;

remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, fb_is_primary_device(fb_info));

num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++)   //1.1在数组registered_fb中搜索没有使用的一项来注册
    if (!registered_fb[i])
        break;
fb_info->node = i;              //1.2这个i值很重要,以后open(/dev/fb0),后面的0,1,2就是这个i
mutex_init(&fb_info->lock);
mutex_init(&fb_info->mm_lock);
//2.在"/dev/grapihc"下创建fb[i]设备文件,fb_class="/dev/graphic"
fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
fb_init_device(fb_info);   //在/sys/device目录下创建/sys文件
if (fb_info->pixmap.addr == NULL) {
    fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
    if (fb_info->pixmap.addr) {
        fb_info->pixmap.size = FBPIXMAPSIZE;
        fb_info->pixmap.buf_align = 1;
        fb_info->pixmap.scan_align = 1;
        fb_info->pixmap.access_align = 32;
        fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
    }
}
fb_info->pixmap.offset = 0;

if (!fb_info->pixmap.blit_x)
    fb_info->pixmap.blit_x = ~(u32)0;

if (!fb_info->pixmap.blit_y)
    fb_info->pixmap.blit_y = ~(u32)0;

if (!fb_info->modelist.prev || !fb_info->modelist.next)
    INIT_LIST_HEAD(&fb_info->modelist);

fb_var_to_videomode(&mode, &fb_info->var);
fb_add_videomode(&mode, &fb_info->modelist);
registered_fb[i] = fb_info;                  //3.将初始化了的fb_info加到全局变量中

event.info = fb_info;
if (!lock_fb_info(fb_info))
    return -ENODEV;
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
unlock_fb_info(fb_info);
return 0;

}
这样就注册好了framebuffer,有了/dev/graphics/fb0,但是文件操作在哪儿呢?
二.上层调用 open /dev/graphics/fb0时
通过register_framebuffer产生了设备文件/dev/graphics/fb0,但是open /dev/graphics/fb0时的文件操作是如何产生的呢?
看一下drivers/video/fbmem.c的注册过程就知道了.
module_init(fbmem_init);
–> fbmem_init
static int __init fbmem_init(void)
{
proc_create(“fb”, 0, NULL, &fb_proc_fops); //创建/proc/fb
register_chrdev(FB_MAJOR,”fb”,&fb_fops); //注册字符设备文件
//创建class=/dev/graphics”,以后用device_create创建的设备文件都会在/dev/graphics目录下
fb_class = class_create(THIS_MODULE, “graphics”);
return 0;
}

注册的文件操作结构体是fb_fops
static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.mmap = fb_mmap,
.open = fb_open,
…. //省略
};

上层调用open /dev/graphics/fb0时,会先调用fb_open函数
static int fb_open(struct inode *inode, struct file *file)
__acquires(&info->lock)
__releases(&info->lock)
{
//从inode中获取次设备号,来判断是哪个fb,并将次设备号转为索引值
int fbidx = iminor(inode);
struct fb_info *info;
int res = 0;

if (fbidx >= FB_MAX)
    return -ENODEV;
info = registered_fb[fbidx];  //通过索引值找在全局数组中找到fb
if (!info)
    request_module("fb%d", fbidx);
info = registered_fb[fbidx];  //通过索引值找在全局数组中找到fb
if (!info)                    //为什么要调两次?
    return -ENODEV;
mutex_lock(&info->lock);
if (!try_module_get(info->fbops->owner)) {  //模块引用计数加1 
    res = -ENODEV;
    goto out;
}
file->private_data = info;
if (info->fbops->fb_open) {              //如果fb0有open函数则调用fb0的open
    res = info->fbops->fb_open(info,1);
    if (res)
        module_put(info->fbops->owner);
}

ifdef CONFIG_FB_DEFERRED_IO

if (info->fbdefio)
    fb_deferred_io_open(info, inode, file);

endif

out:
mutex_unlock(&info->lock);
return res;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值