linux驱动 struct file_operations 解析

目录

 

file_oprations整体解析

int (*open) (struct inode *, struct file *);

int (*release) (struct inode *, struct file *);

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

copy_to_user      copy_from_user


 

 

file_oprations整体解析

struct file_operations { 
  struct module *owner;//拥有该结构的模块的指针,一般为THIS_MODULES  
   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);//仅用于读取目录,对于设备文件,该字段为NULL   
   unsigned int (*poll) (struct file *, struct poll_table_struct *); //轮询函数,判断目前是否可以进行非阻塞的读写或写入   
  int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); //执行设备I/O控制命令   
  long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); //不使用BLK文件系统,将使用此种函数指针代替ioctl  
  long (*compat_ioctl) (struct file *, unsigned int, unsigned long); //在64位系统上,32位的ioctl调用将使用此函数指针代替   
  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); //通知设备FASYNC标志发生变化   
  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 **);   
};

 

int (*open) (struct inode *, struct file *);

在操作设备前必须先调用open函数打开文件,可以干一些需要的初始化操作。当然,如果不实现这个函数的话,驱动会默认设备的打开永远成功。打开成功时open返回0。

 

int (*release) (struct inode *, struct file *);

当设备文件被关闭时内核会调用这个操作,当然这也可以不实现,函数默认为NULL。关闭设备永远成功。

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

与用户层的read对应:ssize_t read(int fd, void *buf, size_t count);

用法:

从设备中读取数据,当用户层调用函数read时,对应的,内核驱动就会调用这个函数。

参数:

struct file:file结构体,现在暂时不用,可以先不传参。

char __user:只看到__user就知道这是从用户态的指针,通过这个指针往用户态传数据。这是对应用户层的read函数的第二个参数void *buf。

size_t:写内核的人就是闲着喜欢编一些奇怪的类型,其实这只是unsigned int。对应应用层的read函数的第三个参数。

loff_t:这是用于存放文件的偏移量的,回想一下系统编程时,读写文件的操作都会使偏移量往后移。不过待会的代码先不实现,迟点会说。

返回值:

当返回正数时,内核会把值传给应用程序的返回值。一般的,调用成功会返回成功读取的字节数

如果返回负数,内核就会认为这是错误,应用程序返回-1

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

与用户层的write对应:ssize_t write(int fd, const void *buf, size_t count);

用法:往设备写入数据,当用户层调用函数write时,对应的,内核驱动就会调用这个函数。

参数:

struct file:file结构体,现在暂时不用,可以先不传参。

char __user:只看到__user就知道这是从用户态的指针,通过这个指针读取用户态的数据。这是对应用户层的write函数的第二个参数const void *buf。

size_t:写内核的人就是闲着喜欢编一些奇怪的类型,其实这只是unsigned int。对应用户层的write函数的第三个参数count

loff_t:这是用于存放文件的偏移量的,回想一下系统编程时,读写文件的操作都会使偏移量往后移。不过待会的代码先不实现,迟点会说。

返回值:

当返回正数时,内核会把值传给应用程序的返回值。一般的,调用成功会返回成功读取的字节数。

如果返回负数,内核就会认为这是错误,应用程序返回-1。

copy_to_user      copy_from_user

 

static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)

static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)

用法:

和memcpy的参数一样,但它根据传参方向的不同分开了两个函数。

"to"是相对于内核态来说的。所以,to函数的意思是从from指针指向的数据将n个字节的数据传到to指针指向的数据。

"from"也是相对于内核来说的。所以,from函数的意思是从from指针指向的数据将n个字节的数据传到to指针指向的数据。

返回值:

函数的返回值是指定要读取的n个字节中还剩下多少字节还没有被拷贝。

注意:

一般的,如果返回值不为0时,调用copy_to_user的函数会返回错误号-EFAULT表示操作出错。当然也可以自己决定。

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(linux,linux驱动开发)