不错,今天walfred将在快速上手linux设备驱动这一块,谈谈linux的设备也符合“一切皆是文件”的思想在linux设备驱动模型应用。如果你不理解Linux设备模型,请看下面:
1.[快速上手Linux设备驱动]之我看Linux设备模型(总线篇)
2.[快速上手Linux设备驱动]之我看Linux设备模型(设备篇)
3.[快速上手Linux设备驱动]之我看Linux设备模型(设备驱动篇)
4.[快速上手Linux设备驱动]之我看Linux设备模型(类子系统篇)
“一切皆是文件”是 Unix/Linux 的基本哲学之一。不仅普通的文件,目录、字符设备、块设备、 套接字等在 Unix/Linux 中都是以文件被对待;它们虽然类型不同,但是对其提供的却是同一套操作界面。
当然,在这里我先给大家上一道预备知识的大菜,不过这边我先暂时小打小闹下,稍微说下,日后详述之。
正文
从上图,我们可以简单的看出一个在user space的应用程序通过系统调用,经过VFS层面,在和设备驱动打交道,最后设备驱动驱动对应设备,这是一个比较简单的描述,如果分析起来也就不难得到:user space的应用程序与VFS的接口就是系统调用,VFS与驱动程序的接口就是file_operations。
关于file_operations
从之前打过交道的字符设备驱动,我们就知道存在了这么一种file_operations结构体,我现在可以说在描述一个设备,我们用户最接近的方法是file_operations,Linux每类设备都定义了文件操作方法,例如,字符设备的操作方法为def_chr_fops,块设备为def_blk_fops,网络设备为bad_sock_fops。每种设备类型底层操作方法是不一样的,但是通过file_operations方法将设备类型的差异化屏蔽了,这就是Linux能够将所有设备都理解为文件的缘由。这里因为我这几天在搞块设备,所以先看下def_blk_fops。
struct file_operations def_blk_fops = {
open:blkdev_open,
release:blkdev_close,
llseek:block_llseek,
read:generic_file_read,
write:generic_file_write,
mmap:generic_file_mmap,
fsync:block_fsync,
ioctl:blkdev_ioctl,
};
设备差异性
到这里,又提出一个问题:既然这样,那设备的差异化又该如何体现呢?在文件系统层定义了文件系统访问设备的方法,该方法就是address_space_operations,文件系统通过该方法可以访问具体的设备。对于字符设备而言,没有实现address_space_operations方法,也没有必要,因为字符设备的接口与文件系统的接口是一样的,在字符设备open操作的过程中,将inode所指向的file_operations替换成cdev所指向的file_operations就可以了。这样用户层读写字符设备可以直接调用cdev中file_operations方法了。
[linux/fs.h]
/*
*Linux页高速缓存实用化address_space结构体描述页高速缓存中的页面
*定义文件在linux/fs.h中
*/
struct address_space {
struct inode*host;/*拥有节点*/
struct radix_tree_rootpage_tree;/*包含全部页面的radix树*/
spinlock_ttree_lock;/*保护page_tree的自旋锁*/
unsigned inti_mmap_writable;/* VM_SHARED记数*/
struct prio_tree_rooti_mmap;/*似有映射链表*/
struct list_headi_mmap_nonlinear;/* VM_NONLINEAR链表*/
spinlock_ti_mmap_lock;/*保护i_mmap的自旋锁*/
atomic_ttruncate_count;/*截断记数*/
unsigned longnrpages;/*页总数*/
pgoff_twriteback_index;/*回写的起始偏移*/
struct address_space_operations*a_ops;/*操作表*/
unsigned longflags;/* gfp_mask掩码与错误标识*/
struct backing_dev_info *backing_dev_info;/*预读信息*/
spinlock_tprivate_lock;/*私有address_space锁*/
struct list_headprivate_list;/*私有address_space链表*/
struct address_space*assoc_mapping;/*相关的缓冲*/
};
/*
*/
struct address_space_operations {
int (*writepage)(struct page *, struct writeback_control *);
int (*readpage) (struct file *, struct page *);
int (*sync_page) (struct page *);
int (*writepages) (struct address_space *, struct writeback_control *);
int (*set_page_dirty) (struct page *);
int (*readpages) (struct file *, struct address_space *,
struct list_head *, unsigned);
int (*prepare_write) (struct file *, struct page *, unsigned, unsigned);
int (*commit_write) (struct file *, struct page *, unsigned, unsigned);
sector_t (*bmap)(struct address_space *, sector_t);
int (*invalidatepage) (struct page *, unsigned long);
int (*releasepage) (struct page *, int);
int (*direct_IO) (int, struct kiocb *, const struct iovec *,
loff_t, unsigned long);
};
到这里,是不是明白了linux的“设备”也是文件了呢