设备文件节点的生成

来源:互联网 发布:企业产品展示网站源码 编辑:程序博客网 时间:2024/03/29 01:01

设备文件节点的生成

在Linux系统下,设备文件是种特殊的文件类型,其存在的主要意义是沟通用户空间程序和内核空间驱动程序。换句话说,用户空间的应用程序要想使用驱动程序提供的服务,需要经过设备文件来达成。当然,如果你的驱动程序只是为内核中的其他模块提供服务,则没有必要生成对应的设备文件。

按照通用的规则,Linux系统所有的设备文件都位于/dev目录下。/dev目录在Linux系统中算是一个比较特殊的目录,在Linux系统早期还不支持动态生成设备节点时,/dev目录就是挂载的根文件系统下的/dev,对这个目录下所有文件的操作使用的是根文件系统提供的接口。比如,如果Linux系统挂载的根文件系统是ext3,那么对/dev目录下所有目录/文件的操作都将使用ext3文件系统的接口。随着后来Linux内核的演进,开始支持动态设备节点的生成[1],使得系统在启动过程中会自动生成各个设备节点,这就使得/dev目录不必要作为一个非易失的文件系统的形式存在。因此,当前的Linux内核在挂载完根文件系统之后,会在这个根文件系统的/dev目录上重新挂载一个新的文件系统devtmpfs,后者是个基于系统RAM的文件系统实现。当然,对动态设备节点生成的支持并不意味着一定要将根文件系统中的/dev目录重新挂载到一个新的文件系统上,事实上动态生成设备节点技术的重点并不在文件系统上面。

动态设备节点的特性需要其他相关技术的支持,在后续的章节中会详细描述这些特性。目前先假定设备节点是通过Linux系统下的mknod命令静态创建。为方便叙述,下面用一个具体的例子来描述设备文件产生过程中的一些关键要素,这个例子的任务很简单:在一个ext3类型的根文件系统中的/dev目录下用mknod命令来创建一个新的设备文件节点demodev,对应的驱动程序使用的设备主设备号为2,次设备号是0,命令形式为:

root@LinuxDev:/home/dennis#mknod /dev/demodev c 2 0

上述命令成功执行后,将会在/dev目录下生成一个名为demodev的字符设备节点。如果用strace工具来跟踪一下上面的命令,会发现如下输出(删去了若干不相关部分):

root@LinuxDev:/home/dennis#strace mknod /dev/demodev c 2 0

execve("/bin/mknod",["mknod", "/dev/demodev", "c","30","0"], [/* 36 vars */]) = 0

mknod("/dev/demodev",S_IFCHR|0666, makedev(30,0)) = 0

可见Linux下的mknod命令最终是通过调用mknod函数来实现的,调用时的重要参数有两个,一是设备文件名("/dev/demodev"),二是设备号(makedev(30,0))。设备文件名主要在用户空间使用(比如用户空间程序调用open函数时),而内核空间则使用inode来表示相应的文件。本书只关注内核空间的操作,对于前面的mknod命令,它将通过系统调用sys_mknod进入内核空间,这个系统调用的原型是:

<include/linux/syscalls.h>

long sys_mknod(const char __user *filename, int mode, unsigned dev);

注意sys_mknod的最后一个参数dev,它是由用户空间的mknod命令构造出的设备号。sys_mknod系统调用将通过/dev目录上挂载的文件系统接口来为/dev/demodev生成一个新的inode[2],设备号将被记录到这个新的inode对象上。

图2-7展示了通过ext3文件系统在/dev目录下生成一个新的设备节点/dev/demodev的主要流程。

图2-7 ext3文件系统mknod的主要流程

完整了解设备节点产生的整个过程需要知晓VFS和特定文件系统的技术细节。然而从驱动程序员的角度来说,没有必要知道文件系统相关的所有细节,只需关注文件系统和驱动程序间是如何建立上关联的就足够了。

sys_mknod首先在根文件系统ext3的根目录“/”下寻找dev目录所对应的inode,图中对应的inode编号为168,ext3文件系统的实现会通过某种映射机制,通过inode编号最终得到该inode在内存中的实际地址(图中由标号1的线段表示)。接下来会通过dev的inode结构中的i_op成员指针所指向的ext3_dir_inode_operations(这是个struct inode_operations类型的指针),来调用该对象中的mknod方法,这将导致ext3_mknod函数被调用。

ext3_mknod函数的主要作用是生成一个新的inode(用来在内核空间表示demodev设备文件节点,demodev设备节点文件与新生成的inode之间的关联在图2-7中由标号5的线段表示)。在ext3_mknod中会调用一个和设备驱动程序关系密切的init_special_inode函数,其定义如下:

<fs/inode.c>

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;

       } else if (S_ISFIFO(mode))

              inode->i_fop =&def_fifo_fops;

       else if (S_ISSOCK(mode))

              inode->i_fop =&bad_sock_fops;

       else

              printk(KERN_DEBUG"init_special_inode: bogus i_mode (%o) for"

                              " inode %s:%lu\n", mode,inode->i_sb->s_id,

                              inode->i_ino);

}

这个函数最主要的功能便是为新生成的inode初始化其中的i_fop和i_rdev成员。设备文件节点inode中的i_rdev成员用来表示该inode所对应设备的设备号,通过参数rdev为其赋值。设备号在由sys_mknod发起的整个内核调用链中进行传递,最早来自于用户空间的mknod命令行参数。

i_fop成员的初始化根据是字符设备还是块设备而有不同的赋值。对于字符设备,fop指向def_chr_fops,后者主要定义了一个open操作:

<fs/char_dev.c>

const struct file_operations def_chr_fops = {

       .open = chrdev_open,

       …

};

相对于字符设备,块设备的def_blk_fops的定义则要有点复杂:

<fs/block_dev.c>

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 = generic_file_aio_read,

       .aio_write       = blkdev_aio_write,

       .mmap           = generic_file_mmap,

       .fsync             = blkdev_fsync,

       .unlocked_ioctl      = block_ioctl,

#ifdef CONFIG_COMPAT

       .compat_ioctl  = compat_blkdev_ioctl,

#endif

       .splice_read    = generic_file_splice_read,

       .splice_write   = generic_file_splice_write,

};

关于块设备,将在本书第11章“块设备驱动程序”中详细讨论,这里依然把考察的重点放在字符设备上。字符设备inode中的i_fop指向def_chr_fops。至此,设备节点的所有相关铺垫工作都已经结束,接下来可以看看打开一个设备文件到底意味着什么。

 

——本段文字节选自《深入Linux设备驱动程序内核机制》

图书详细信息:



http://blog.csdn.net/broadview2006/article/details/7281061

[1] 这里动态生成设备节点的说法是相对于使用mknod命令生成设备节点而言的,前者直接通过文件系统接口来生成对应的设备节点。

[2] 对于实际的文件系统,比如ext3文件系统,产生一个node的过程因为同时要涉及底层存储设备的操作,因而会变得很复杂。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 ps中抠出的图边缘虚不圆滑怎么办 ps的文字工具多了圆框怎么办 苹果6s屏幕锁忘了密码怎么办 网上下载的3d模型渲染很慢怎么办 cad下载完成后出现闪退怎么办 婴儿在肚子里被系带绑到怎么办 我想给外地的朋友送花怎么办 英雄联盟连接不上聊天服务器怎么办 用黄金换玫瑰金后悔了怎么办 劳力士日志系列玫瑰金和黄金怎么办 香菇代进地注水后长满绿毛怎么办 群主给你带了不满意的头衘怎么办 普兰德雪地靴洗变色了怎么办 书被水泡了皱了黏了怎么办 书被水泡了皱了没干怎么办 眼皮干燥起皮起皱怎么办能治好吗 手指头起小水泡指甲不平整怎么办 这几天我的内裤上带点血丝怎么办 一个月宝宝私处捂白了怎么办 工资算了字签了老板没把钱怎么办 百合种球叶子都变黄了怎么办 新买的富贵竹叶子发黄怎么办水养 朋友总是以隐私为借口欺骗我怎么办 三星手机版本低下载不了微信怎么办 选了动漫制作技术但不会画画怎么办 做主播高薪可是心累不愿做了怎么办 pr导出的avi无压缩太大怎么办 捡了个小米max被绑定了怎么办 二十岁时头发开始掉了怎么办 在酒店换衣服忘记关窗帘了怎么办 淘宝店铺装修更改图片要收费怎么办 惠阳市教育考试考证号忘记怎么办 高考完被被骗去读自考以后怎么办 孩子学习遇到瓶颈期了老师该怎么办 微信家长群有不好的言论出现怎么办 铃木汽车后备箱电动锁没有电怎么办 坐飞机没有连号座位带孩子怎么办 白沙的衣服洗衣服时染上颜色怎么办 网购商家少发了货怎么办 我想成为安利的员工怎么办会员 安利皇后锅锅盖吸在桌子上怎么办