第6章 设备驱动程序(2)

目录

6.3 和文件系统关联

6.3.1 inode的设备文件成员

6.3.2 标准文件操作

6.3.3 字符设备的标准操作

6.3.4 块设备的标准操作

6.4 字符设备操作

6.4.1 表示字符设备

6.4.2 打开设备文件

6.4.3 读写操作


本专栏文章将有70篇左右,欢迎+关注,查看后续文章。

6.3 和文件系统关联

普通文件和设备文件都通过相同接口访问。

6.3.1 inode的设备文件成员

每个文件都有一个inode,用于存储文件属性。

struct         inode {

        dev_t                 i_rdev;

                //主,从设备号。

        umode_t           i_mode;

                //文件类型。如socket,fifo,block,char,dir,link

        struct file_operations         *i_fop;

                //供VFS调用,用于读写该文件。

        union {

                struct block_device         *i_bdev;

                struct cdev                       *i_cdev;

        }

}

unsigned imajor(const struct inode *inode)

unsigned iminor(const struct inode *inode)

        这两个函数可分别得到主设备号,从设备号。

6.3.2 标准文件操作

当创建设备文件时(如mknod命令),各种文件系统都调用init_special_inode,以创建inode。

void   init_special_inode(struct inode   *inode,    umode_t mode,    dev_t    rdev)

{

        inode->i_mode    =    mode;

        if (S_ISCHR(mode)) {         //字符设备

                inode->i_fop    =    &def_chr_fops;

                inode->i_rdev    =     rdev;

        } else if (S_ISBLK(mode)) {         //块设备

                inode->i_fop     =     &def_blk_fops;

                inode->i_rdev    =    rdev;

        }

}

jffs2_mknod/ubifs_mknod/logfs_mknod:

        都会调用init_special_inode。

6.3.3 字符设备的标准操作

只有一个open操作, 没有读写操作。

struct file_operations         def_chr_fops = {

        .open    =    chrdev_open,

};

chrdev_open(struct inode *inode, struct file *filp)

        将调用struct file *filp->f_op->open(inode, filp),从而操作设备自身。

此处只定义一个open函数。因为其他read,write,mmap等函数通常由设备文件自定义实现。

6.3.4 块设备的标准操作

const struct file_operations    def_blk_fops = {

        .open    =     blkdev_open,

        .release    =     blkdev_close,

        .llseek    =     block_llseek,

        .read   =   do_sync_read,

        .write   =   do_sync_write,

        .aio_read   =   blkdev_aio_read,

        .aio_write   =   blkdev_aio_write,

        .mmap   =   generic_file_mmap,

        .fsync   =   blkdev_fsync,

        .unlocked_ioctl   =   block_ioctl,

        .splice_read   =   generic_file_splice_read,

        .splice_write   =   generic_file_splice_write,

};

VFS调用file_operations,而file_operations调用block_device_operations中的函数。

struct file_operations         def_blk_fops:

        所有块设备通用实现。

block_device_operations:

        对各种块设备具体独立实现。

6.4 字符设备操作

6.4.1 表示字符设备

struct         cdev {

        struct kobject        kobj;         //内核对象

        struct module        *owner;

        struct file_operations   *ops;

        struct list_head      list;         //连接所有表示该设备文件的inode

        dev_t                     dev;                 //设备号

        unsigned int          count;

}

6.4.2 打开设备文件

//创建设备文件时(mknod)

void   init_special_inode(struct inode   *inode,   umode_t   mode,   dev_t   rdev)

{

        if (S_ISCHR(mode))

                inode->i_fop   =   &def_chr_fops;         //创建设备文件时就已经初始化好

}

const struct file_operations   def_chr_fops   =   {

        .open   =   chrdev_open,

        .llseek   =   noop_llseek,

};

打开设备文件时执行chrdev_open。

int   chrdev_open(struct inode   *inode,   struct file   *filp)

{

        struct cdev   *cdev;

        struct kobject   *kobj;

        int   idx;

        kobj   =   kobj_lookup(cdev_map,   inode->i_rdev,   &idx);

                //查找设备文件对应kobject。

        cdev   =   container_of(kobj,   struct cdev,   kobj);

                //得到struct cdev实例。

        inode->i_cdev   =   cdev;

                //保存,后续次直接用,不用查找了。

        filp->f_op   =   fops_get(cdev->ops);

        filp->f_op->open(inode,   filp);

                //最终调用该字符设备自定义的open函数。

        return 0;

}

打开上述设备,依次对应如下函数。

创建设备文件时,创建一个struct inode。

打开设备文件时,创建一个struct file。

6.4.3 读写操作

不同设备各自实现struct file_operations中read/write函数。

  • 52
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山下小童

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值