而一提到字符设备,马上就想起了LInux字符设备框架,cdev神马的。之前一直以为将块设备模拟为字符设备有额外的代码:做一个字符设备驱动来适配对块设备的操作。后来发现平时dd的设备文件就是一个块设备文件。那read,write请求都走到哪里去了呢?
VFS层中open流程有一步是设置file的ops。这个ops跳转表是从inode得到的,在open时将其赋于file的成员,以后引用file就可以进行文件操作;如果ops->open不为空,还会顺便调用之。打开一个字符设备(c)时,字符设备文件inode里的ops为def_chr_fops,只里仅定义了open操作(chrdev_open)。注册一个字符设备驱动就是将驱动提供的ops跳转表与某段设备号相关联(实际上是将cdev与某段设备号相关联,fops作为cdev的一个成员)。而chrdev_open则进行相反的操作:查询给定设备号是否fops与之关联。如果有,则将这个fops赋给file的相关字段(覆盖了def_chr_fops),新的ops->open不为空的话,调用之(给驱动一个初始化机会;这已经是第三次open了)。以后对这个文件的操作则由驱动提供了ops跳转表来支撑。
如果直接打开一个块设备文件(b),VFS给file的ops赋值时,从inode得到的是def_blk_fops。def_chr_fops只定义了open方法,这个open方法会陷到字符设备系统里。而def_blk_fops整定义了一整套方法。def_chr_fops只起过渡作用,它的open方法要去寻找硬件驱动的支撑;def_blk_fops则直接提供了所有支持。至于对硬件信赖,好像被page cache屏蔽掉了。