Linux字符设备驱动(三)-文件操作函数实现
来源:互联网 发布:反刍动物牛羊配方软件 编辑:程序博客网 时间:2024/04/28 06:45
前面已经成功的注册了一个字符设备驱动了,不过呢,还有一个结构体是空的,就是file_operations,这个结构体是字符设备驱动的核心东西了,前面也说过,字符设备驱动其实就是实现这个结构体里的函数了.这个结构体比较庞大啊,好像比我电脑的屏幕大多了,不过,这里的结构体是按需实现,也就是说你不需要全部实现,按特定情况实现就是了,比如一个字符设备驱动在最简的时候只需要实现 ioctl这一个函数就可以了!下面还是来看一下这个结构体吧:
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 *, loff_t, loff_t, 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);
};下面简单说一下常用的几个吧,其余的我也不知道了,又忘了,选择性失忆:
struct module *owner; //一般直接指定为THIS_MODULE
1:文件指针操作函数
这个函数是文件指针操作函数,对应于系统调用的 off_t lseek(int fildes, off_t offset, int whence),这个系统调用做什么的我又忘了,自己查去.当我们调用这个系统调用操作字符设备的时候,那么实际上就会调用这个结构体里的这个函数.第一个参数是文件指针,第二个参数是移动的字节数,第三个参数是相对位置.原形如下:
loff_t (*llseek) (struct file *filp, loff_t offset, int whence);
2:文件打开函数
此函数将在我们对字符设备节点进行打开操作的时候,也就是使用系统调用的open函数的时候调用.第一个参数是inode形的结构体,这表示一个文件,就是我们的字符设备文件结点,是内核内部用来表示文件的,第二个参数表示打开的文件,一个文件可以被打开多次,所以会有多个filp存在.正常情况下这个函数运行成功应该返回0;我们可以在这个函数里做一些对设备的打开操作,等.
int (*open) (struct inode * ind, struct file * filp);
3:读数据操作函数
这个函数就是用户空间要从字符设备里读数据的时候调用read系统调用的时候调用的,第一个参数是打开的文件指针,第二个参数是用户空间的缓冲区地址,第三个参数size_t size是要读的字节数,第4个参数loff_t * offset是文件指针;注意这个文件指针,我们在用户空间调用read,write系统调用每读一次文件的时候是不是文件指针都会自动移动吗?就是这个参数,在驱动里需要我们自己维护这个参数,当然内核不会帮你做,我也不可能帮你做的,上帝更不会了,所以不要忘了!当然如果你不需要这个参数,也可以不处理它.函数正常处理后应该返回读取的字节数,错误返回小于0的值;
ssize_t (*read) (struct file *filp, char __user * buff, size_t size, loff_t * offset);
注意:这里的读取是从内核空间把数据往用户空间copy,当然我们不能直接使用memcpy这样的函数,内核提供了2个函数来做这些事情,一个是内核向用户空间copy,一个是用户空间向内核copy.函数远行如下:
unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);
unsigned long copy_from_user(void *to, const void __user *from, unsigned long n);
我们应该检测这个2个函数的返回值,以判断是否执行成功,因为内核认为这2个函数的执行是很重要的,所以一定要对它们进行检测,看是否运行成功.记住这函数如果copy成功,将会返回0,如果没有copy成功,将会返回没有copy成功的字节数.
4:写数据操作函数
这个函数就是用户空间向内核写数据的时候所调用的函数,这个函数的参数和读操作函数一样,在操作成功后,应该返回实际写入的字节数,如操作失败,则应该返回小于0的值.同样应该使用内核提供的copy_from_user函数来操作数据。
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
5:文件关闭函数
这个函数是在调用close系统调用的时候调用的,基本上做和open函数向反的工作,就不多写了。原形如下啊:
int (*release) (struct inode *, struct file *);
总结:今天没写什么,就是抄了不少东西过来,呵呵,这样抄一次,选择性失忆的可能性就小多了!ps:open和release如果不实现,内核是会提供一个默认的函数的。
- Linux字符设备驱动(三)-文件操作函数实现
- Linux字符设备驱动(三)
- Linux字符设备驱动(三)
- Linux字符设备驱动(三)
- Linux字符设备驱动(三)
- Linux 设备驱动之字符设备(三)
- Linux 设备驱动之字符设备(三)
- linux 驱动-----字符设备globalmem驱动实现
- linux驱动开发--字符设备:原子操作
- Linux驱动编程--字符设备文件注册
- 第三章字符设备驱动(2)—设备操作函数
- Linux设备驱动之字符设备(三)
- 字符设备驱动--- 设备操作
- 【嵌入式Linux驱动开发】三、字符设备驱动(一)
- 【嵌入式Linux驱动开发】三、字符设备驱动(二)
- 【Linux开发】linux设备驱动归纳总结(三):2.字符型设备的操作open、close、read、write
- 字符设备驱动函数
- linux设备驱动开发-高级字符设备操作poll
- [Borland.Delphi.V1.V2.V.3.古董.怀旧.供爱好者收藏用].Borland.Delphi2.rar
- 发个Java分页代码
- 利用Jena进行推理
- [Borland.Delphi.V1.V2.V.3.古董.怀旧.供爱好者收藏用].Borland.Delphi3.rar
- 求无向连通图的最小生成树算法——Prim与Kruska
- Linux字符设备驱动(三)-文件操作函数实现
- 我的编程风格:
- proj4库的编译与简单使用
- cocos2d-x坐标系
- first
- PHP学习——第一章
- 一个空类被编译器编译后产生了哪些默认函数
- 谁动了我的cpu——oprofile使用札记
- 设计模式三(采用pyside为设计模式一、二增加GUI外衣 )