Linux设备驱动

设备驱动程序

本次来分享下我在Linux设备驱动这里的学习收获。
首先要区分一下设备驱动,和设备驱动程序,在我的理解中,设备驱动是内核层面面向数据结构的概念;而设备驱动程序则是分为字符设备,I/O设备等的程序,这个里面定义并实现了我们用户在写程序时所使用的open(),write()等的函数;再往下一层则是具体的物理设备和我们平时所书写的驱动物理设备的程序。所以设备驱动程序可以分为两类,一类是字符设备,I/O设备,块设备这三种大的分类,他们定义了open(),write()等的基本函数,另一类就是具体设备的驱动程序,这些一般都是开发人员来写,在使用基本函数的基础上进行设备驱动开发,在最后给与用户一个集成的设备驱动函数接口。我一开始这些还有些分不清,不过在读源码之后有了一些理解,如果有不足的地方,希望能够得到指正。

这里我主要根据设备驱动程序的数据结构来入手,linux下的设备驱动程序最重要的几个数据结构是file,file_operations,和inode。它们都在内核中include/linux/fs.h文件中,这里需要说明下,文件系统相关的几个数据结构也都在这里面,这时就可以看出linux内核的知识实际上是统合在一起的,书本上的是人为划分,学习时一定要看源码,就可以将书本上的学习内容链接起来,原来我以为文件系统和驱动程序的数据结构是分开的,没想到找半天在一个文件中。(ps:dentry数据机构在dcache.h文件中,至于为什么没有和其他三个数据结构在一起我还没有搞清,不过fs.h文件的头文件包括了dcache,所以在运行的时候并不影响)下面是fs.h文件中的file,file_operations和inode数据结构:

struct file {
	...
	struct path		f_path;
	struct inode		*f_inode;	/* cached value */
	const struct file_operations	*f_op;
	...
};
struct file_operations {
	struct module *owner;
	loff_t (*llseek) (struct file *, loff_t, int);
	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
	ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
	ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
	int (*iterate) (struct file *, struct dir_context *);
	...
};


struct inode {
	umode_t			i_mode;
	unsigned short		i_opflags;
	kuid_t			i_uid;
	kgid_t			i_gid;
	unsigned int		i_flags;
       const struct inode_operations	*i_op;
	struct super_block	*i_sb
	struct address_space	*i_mapping;
	...
};

这里我们可以看到file中会有file_operations和inode的调用,而在file_operations中我们可以看到这个结构中基本都是各个驱动程序可能会用到的函数接口,例如常用到的read,write,open,而在inode则是文件系统中的索引节点,存放了处理文件所需要的所有信息,并且有指针指向超级块结构。这里就可以看出linux设备驱动程序的思想,它把所有设备都当做文件,分配文件所需要的索引节点等一切东西,操作时则是和文件一样,分配file_operations,这里面有文件操作程序。大概的流程图如下。

可以看出整个流程是用户->文件系统->设备驱动程序->设备控制器->物理设备
file用来链接文件系统和设备驱动程序

这里就会有问题了,首先是能不能绕过file,直接将inode和file_operations链接起来,比如在嵌入式的简单操作系统中,设备文件都比较少。答案当然是不能,原因也很简单,就是只要操作文件,就会调用file,除非直接不用linux使用的VFS文件结构,不过改了之后可能就不是linux了哈。另外在这个文件中我们也可以发现,super_block有super_block_operations,inode有inode_operations,可以看出设备启动程序调用了file结构和它的file_operations,和而在file结构中本身的文件结构就调用了inode结构,设备驱动程序直接就顺着inode链接起来了设备和文件,可以说设备驱动程序操作也就是文件系统的范畴。

下面还有问题就是,操作系统中存在这么多驱动程序,我咋知道我这个设备就是调用相应的驱动?或者说我现在在操作系统中安装了一个驱动,那么我操作原来的文件会不会用新驱动里的函数来操作?答案当然是不会,这里就有一个操作 mknod /dev/xxx c yyy 0;这里面mknod命令大家自己查查,我就说下这个命令的作用,其中/dev/xxx是设备映射到文件系统中的文件,yyy是设备的主设备号,c是字符设备,命令的意思就是将设备链接到yyy设备号上。下面有一段程序

MODULE_LICENSE("GPL");

#define MYCDEV_MAJOR 231     //cat /proc/devices查看系统中未使用的字符设备主设备号
#define MYCDEV_SIZE 1024

程序中#define MYCDEV_MAJOR 231就是定义了主设备号,这个程序就是一个驱动程序的部分,可以看出231这个设备号就是连接驱动和设备的桥梁,一般的文件或者设备调用默认的驱动,而自己加入的驱动就要和相应的设备链接起来。
这里有个例子

kecheng程序访问的是globa文件,调用的是globalmem驱动,Kecheng1程序访问的是mycdev文件,调用的是mycdev驱动。我的理解是在上面创建文件节点的工作中就将文件和驱动链接起来的,通过文件节点231(mycdev)或者230(globa),所以调用的驱动是对应的,所以在自己写驱动时,除了要将设备映射到目录下成为一个文件之外,还要分配特定的文件节点链接文件和驱动。

关于设备驱动我的理解现在就是这样,设备驱动程序说道理是文件操作,还是属于文件系统的范畴,在学习时,还是要打破书中的章节界限,那只是人为的划分,在源码中都是综合在一起的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值