为了学好字符设备驱动,一些相关结构不得不了解。。。于是,通过Source Insight打开内核。。。我浏览到了驱动重要的相关结构
*用户跟驱动关系:用户空间的read、write等--->linux系统调用--->间接调用设备驱动程序中file_operations结构中的函数(看个例子理解下)
1.struct file_operations学驱动必须了解的结构
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 (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); //文件描述符的读取写入是否阻塞 int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); //命令控制设置 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); //设备内存映射到进程空间 int (*open) (struct inode *, struct file *); //打开设备 int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); //关闭设备 int (*fsync) (struct file *, struct dentry *, int datasync); int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock **); };
2.文件结构 代表一个打开的文件描述符,它不是专门给驱动程序使用的,系统中每一个打开的文件在内核中都有一个关联的struct file。它由内核在open时创建,并传递给在文件上操作的任何函数,直到最后关闭。当文件的所有实例都关闭之后,内核释放这个数据结构
struct file { /* * fu_list becomes invalid after file_free is called and queued via * fu_rcuhead for RCU freeing */ union { struct list_head fu_list; struct rcu_head fu_rcuhead; } f_u; struct path f_path; //文件路径 #define f_dentry f_path.dentry #define f_vfsmnt f_path.mnt const struct file_operations *f_op; //文件操作符结构 spinlock_t f_lock; /* f_ep_links, f_flags, no IRQ */ atomic_long_t f_count; unsigned int f_flags; //文件标识,可写,可读 fmode_t f_mode; loff_t f_pos; //文件读写位置 struct fown_struct f_owner; const struct cred *f_cred; struct file_ra_state f_ra; u64 f_version; #ifdef CONFIG_SECURITY void *f_security; #endif /* needed for tty driver, and maybe others */ void *private_data; #ifdef CONFIG_EPOLL /* Used by fs/eventpoll.c to link all the hooks to this file */ struct list_head f_ep_links; #endif /* #ifdef CONFIG_EPOLL */ struct address_space *f_mapping; #ifdef CONFIG_DEBUG_WRITECOUNT unsigned long f_mnt_write_state; #endif };
3.内核中用inode结构表示具体的文件
struct inode { struct hlist_node i_hash; struct list_head i_list; struct list_head i_sb_list; struct list_head i_dentry; unsigned long i_ino; atomic_t i_count; unsigned int i_nlink; uid_t i_uid; gid_t i_gid; dev_t i_rdev; u64 i_version; loff_t i_size; #ifdef __NEED_I_SIZE_ORDERED seqcount_t i_size_seqcount; #endif struct timespec i_atime; struct timespec i_mtime; struct timespec i_ctime; unsigned int i_blkbits; blkcnt_t i_blocks; unsigned short i_bytes; umode_t i_mode; spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ struct mutex i_mutex; struct rw_semaphore i_alloc_sem; const struct inode_operations *i_op; const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ struct super_block *i_sb; struct file_lock *i_flock; struct address_space *i_mapping; struct address_space i_data; #ifdef CONFIG_QUOTA struct dquot *i_dquot[MAXQUOTAS]; #endif struct list_head i_devices; union { struct pipe_inode_info *i_pipe; struct block_device *i_bdev; struct cdev *i_cdev; }; int i_cindex; __u32 i_generation; #ifdef CONFIG_DNOTIFY unsigned long i_dnotify_mask; /* Directory notify events */ struct dnotify_struct *i_dnotify; /* for directory notifications */ #endif #ifdef CONFIG_INOTIFY struct list_head inotify_watches; /* watches on this inode */ struct mutex inotify_mutex; /* protects the watches list */ #endif unsigned long i_state; unsigned long dirtied_when; /* jiffies of first dirtying */ unsigned int i_flags; atomic_t i_writecount; #ifdef CONFIG_SECURITY void *i_security; #endif void *i_private; /* fs or device private pointer */ };
参考资料:http://www.cnblogs.com/QJohnson/archive/2011/06/24/2089414.html
4.cdev结构
在Linux2.6内核中一个字符设备用cdev结构来描述,其定义如下:
struct cdev { struct kobject kobj; struct module *owner; //所属模块 const struct file_operations *ops; //文件操作结构,在写驱动时,其结构体内的大部分函数要被实现 struct list_head list; dev_t dev; //设备号,int 类型,高12位为主设备号,低20位为次设备号 unsigned int count; };
可以使用如下宏调用来获得主、次设备号:
MAJOR(dev_t dev)
MINOR(dev_t dev)
MKDEV(int major,int minor) //通过主次设备号来生成dev_t
5.混杂设备miscdevice结构
struct miscdevice { int minor; const char *name; const struct file_operations *fops; struct list_head list; struct device *parent; struct device *this_device; };