字符设备驱动框架学习总结
2014-03-08 11:33
387 查看
0:字符驱动框架图
1:数据结构
1:struct cdev
struct cdev { struct kobject kobj; struct module *owner; const struct file_operations *ops; struct list_head list; dev_t dev; unsigned int count; };
dev_t dev:设备号,32位。高12位为主设备号,地20位为次设备号。
使用下面宏获取主次设备号:
MAJOR(dev_t dev)
MINOR(dev_t dev)
由主次设备号生成设备号:
MKDEV(int major,int minor)
2: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 *); 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 *, 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 **); long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len); };
3:struct file
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 */ #ifdef CONFIG_SMP int f_sb_list_cpu; #endif 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 };
4:struct inode
struct inode { /* RCU path lookup touches following: */ umode_t i_mode; uid_t i_uid; gid_t i_gid; const struct inode_operations *i_op; struct super_block *i_sb; spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ unsigned int i_flags; struct mutex i_mutex; unsigned long i_state; unsigned long dirtied_when; /* jiffies of first dirtying */ struct hlist_node i_hash; struct list_head i_wb_list; /* backing dev IO list */ struct list_head i_lru; /* inode LRU list */ struct list_head i_sb_list; union { struct list_head i_dentry; struct rcu_head i_rcu; }; unsigned long i_ino; atomic_t i_count; unsigned int i_nlink; dev_t i_rdev;//包含了真正的设备编号 unsigned int i_blkbits; 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; blkcnt_t i_blocks; unsigned short i_bytes; struct rw_semaphore i_alloc_sem; const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ 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; //该成员表示字符设备在内核的 内部结构。当inode指向一个字符设备文件时,该成员包含了指向struct cdev结构的指针,其中cdev结构是字符设备结构体。
5:特定设备相关的数据结构,保存驱动程序使用的信息
struct file:代表一个打开的文件描述符,它不是专门给驱动程序使用的,系统中每一个打开的文件在内核中都有一个关联的struct file。它由内核在open时创建,并传 递给在文件上操作的任何函数,直到最后关闭。struct inode:索引节点。每个存储设备或存储设备的分区(存储设备是硬盘、软盘、U盘 ... ... )被格式化为文件系统后,应该有两部份,一部份是inode,另一部份是 Block,Block是用来存储数据用的。而inode呢,就是用来存储这些数据的信息,这些信息包括文件大小、属主、归属的用户组、读写权限等。inode为每个文件进行信息索引,所以就有了inode的数值。操作系统根据指令,能通过inode值最快的找到相对应的文件。
做个比喻,比如一本书,存储设备或分区就相当于这本书,Block相当于书中的每一页,inode 就相当于这本书前面的目录,一本书有很多的内容,如果想查找某部份的内容,我们可以先查目录,通过目录能最快的找到我们想要看的内容。
一般情况下,cdev对象嵌入在特定设备结构中xxx_cdev。
使用文件私有数据:设备驱动可以支持多个设备,为了使驱动程序结构简单,我们通常把xxx_cdev地址则保存在struct file:void *private_data字段中,方便其它操作函数使用。
container_of(ptr, type, member):第一个参数是结构体成员的指针,第二参数是整个结构体的类型,第三个参数是结构体成员的类型。
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
2:重要函数接口
字符驱动框架提供的重要函数实现了驱动程序和内核的无缝连接。int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
const char *name);
动态申请主设备号,第二个参数起始次设备号,第三个参数是此设备号数目,最后一个参数是设备名称,出现在/proc/devices中。
void unregister_chrdev_region(dev_t from, unsigned count)
注销主设备号
void cdev_init(struct cdev *, const struct file_operations *);
把设备操作集和字符设备关联
int cdev_add(struct cdev *, dev_t, unsigned);
设备号和字符设备绑定
void cdev_del(struct cdev *);
删除一个字符设备
3:字符驱动程序初始化流程
1:申请分配主设备号2:为特定的设备相关的数据结构分配内存
3:把接口函数与字符设备程序的cdev抽象关联
4:把主设备号和驱动程序的cdev关联
5:在/dev和/sys下创建节点
6:初始化硬件
相关文章推荐
- 看得懂吗?好莱坞电影中的神秘程序代码
- 【Android-jni】JNI学习第一天
- Ubuntu vlc vod 服务器
- java常用排序算法
- hdu1500 动态规划
- Spiral Matrix II
- 键盘无Break键,CRT中映射的方法
- 笔记1
- JAVA实践(二)————五子棋
- Random类 (java.util)
- 正则表达式贪婪与非贪婪模式
- 2011蓝桥杯【初赛试题】程序设计题一
- 工程文件存储策略,实现前后兼容打开。
- asp.net 的所有控件都必须放置在<form runat=server><form>内吗?
- Generate Parentheses
- javaweb之request通过各种表单提交项收集用户数据和用request获取表单提交数据
- &和&&的区别
- 利用成功学思维做好网站运营
- 驱动程序开发学习(一)概述
- 大小端(字节序)位序