linux驱动开发之字符设备框架 -调用过程分析

来源:互联网 发布:火锅烧烤网络营销策划 编辑:程序博客网 时间:2024/06/05 20:08

前言

在前边三节的基础上,粗略的分析一下,上层应用调用到驱动程序的过程,分为下面几个方面:
1.字符设备驱动本身
2.mknod的作用
3.open的调用过程

正文

字符设备驱动本身

start_kernel(kernel-3.10\init\main.c)//启动内核        vfs_caches_init(totalram_pages);        ---------             vfs_caches_init (kernel-3.10\fs\dcache.c)                    inode_init(); //节点初始化                    chrdev_init();//字符设备 (kernel-3.10\fs\Char_dev.c)                            //得到一个kobj_map 类型的cdev_map,用户字符设备的设备号                            cdev_map = kobj_map_init(base_probe, &chrdevs_lock);                                              //涉及到cdev_map的一些操作函数:cdev_add cdev_del chrdev_open。 

mknod

mknod 命令简历一个目录项和一个特殊文件的对应索引点。
mknod的系统调用过程,看参考文献。
在这个过程中,会调用 init_special_inode 这个函数,

void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) (kernel-3.10\fs\Inode.c) {    inode->i_mode = mode;    if (S_ISCHR(mode)) {        inode->i_fop = &def_chr_fops; // 这个给inode的i_fop 赋值为 def_chr_fops,        inode->i_rdev = rdev;          //inode->i_rdev 赋值为设备号        }def_chr_fops的内容/* * Dummy default file-operations: the only thing this does * is contain the open that then fills in the correct operations * depending on the special file... */const struct file_operations def_chr_fops = {    .open = chrdev_open,    .llseek = noop_llseek,};

可以看出def_chr_fops是一个 file_operations类型的变量,其有个成员open,被赋值为 chrdev_open

/* * Called every time a character special file is opened */static int chrdev_open(struct inode *inode, struct file *filp){    struct cdev *p;    struct cdev *new = NULL;    int ret = 0;    spin_lock(&cdev_lock);    p = inode->i_cdev; //节点中得到字符设备    if (!p) {        struct kobject *kobj;        int idx;        spin_unlock(&cdev_lock);        kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); // 当调用这个的opend的时候,会根据设备号在cdev_map中查找设备        if (!kobj)            return -ENXIO;        new = container_of(kobj, struct cdev, kobj);        spin_lock(&cdev_lock);        /* Check i_cdev again in case somebody beat us to it while           we dropped the lock. */        p = inode->i_cdev;        if (!p) {            inode->i_cdev = p = new;            list_add(&inode->i_devices, &p->list);            new = NULL;        } else if (!cdev_get(p))            ret = -ENXIO;    } else if (!cdev_get(p))        ret = -ENXIO;    spin_unlock(&cdev_lock);    cdev_put(new);    if (ret)        return ret;    ret = -ENXIO;    filp->f_op = fops_get(p->ops);    if (!filp->f_op)        goto out_cdev_put;    if (filp->f_op->open) {        ret = filp->f_op->open(inode, filp); //调用字符设备的open函数        if (ret)            goto out_cdev_put;    }    return 0; out_cdev_put:    cdev_put(p);    return ret;}

open的调用过程

应用程序调用open,会 调用系统的sys_open函数
最终会调用到

struct file *dentry_open(const struct path *path, int flags,const struct cred *cred)(kernel-3.10\fs\Open.c)    f->f_flags = flags;    f->f_path = *path;    rror = do_dentry_open(f, NULL, cred);            struct inode *inode;            inode = f->f_inode = f->f_path.dentry->d_inode;             f->f_op = fops_get(inode->i_fop);//获得设备节点对应的fops结构体。会是def_chr_fops 这个结构体                if (!open && f->f_op)                open = f->f_op->open; // 会调用def_chr_fops结构体的open,即chrdev_open。调用过程,看    mknod  部分的介绍

总结

使用mknod 创建节点,在创建过程中的def_chr_fops的open,会起一个 中转的作用。 在调用open打开设备的时候,
会调用到设备本身的open函数,实现打开设备的功能。
目前的代码,我们是手动的调用mknod创建节点。除了手动创建设备节点,linux还提供了 class_create(),device_create自动创建设备文件结点

参考文献

字符设备文件的打开
Linux系统调用(syscall)原理
Linux内核源代码情景分析-系统调用mknod
class_create(),device_create自动创建设备文件结点

0 0