×

Linux设备驱动开发之字符设备驱动编程分析

消耗积分:1 | 格式:rar | 大小:0.6 MB | 2017-10-18

分享资料个

1.字符设备驱动编写流程
  设备驱动程序可以使用模块的方式动态加载到内核中去。加载模块的方式与以往的应用程序开发有很大的不同。以往在开发应用程序时都有一个main()函数作为程序的入口点,而在驱动开发时却没有main()函数,模块在调用insmod命令时被加载,此时的入口点是init_module()函数,通常在该函数中完成设备的注册。同样,模块在调用rmmod命令时被卸载,此时的入口点是cleanup_module()函数,在该函数中完成设备的卸载。在设备完成注册加载之后,用户的应用程序就可以对该设备进行一定的操作,如open()、read()、write()等,而驱动程序就是用于实现这些操作,在用户应用程序调用相应入口函数时执行相关的操作,init_module()入口点函数则不需要完成其他如read()、write()之类功能。
  上述函数之间的关系如图11.3所示。
  Linux设备驱动开发之字符设备驱动编程分析
  图11.3 设备驱动程序流程图
  2.重要数据结构
  用户应用程序调用设备的一些功能是在设备驱动程序中定义的,也就是设备驱动程序的入口点,它是一个在《linux/fs.h》中定义的struct file_operations结构,这是一个内核结构,不会出现在用户空间的程序中,它定义了常见文件I/O函数的入口,如下所示:
  struct file_operations
  {
  loff_t (*llseek) (struct file *, loff_t, int);
  ssize_t (*read) (struct file *filp,
  char *buff, size_t count, loff_t *offp);
  ssize_t (*write) (struct file *filp,
  const char *buff, size_t count, loff_t *offp);
  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);
  int (*mmap) (struct file *, struct vm_area_struct *);
  int (*open) (struct inode *, struct file *);
  int (*flush) (struct file *);
  int (*release) (struct inode *, struct file *);
  int (*fsync) (struct file *, struct dentry *);
  int (*fasync) (int, struct file *, int);
  int (*check_media_change) (kdev_t dev);
  int (*revalidate) (kdev_t dev);
  int (*lock) (struct file *, int, struct file_lock *);
  };
  这里定义的很多函数是否跟第6章中的文件I/O系统调用类似?其实当时的系统调用函数通过内核,最终调用对应的struct file_operations结构的接口函数(例如,open()文件操作是通过调用对应文件的file_operations结构的open函数接口而被实现)。当然,每个设备的驱动程序不一定要实现其中所有的函数操作,若不需要定义实现时,则只需将其设为NULL即可。
  struct inode结构提供了关于设备文件/dev/driver(假设此设备名为driver)的信息,struct file结构提供关于被打开的文件信息,主要用于与文件系统对应的设备驱动程序使用。struct file结构较为重要,这里列出了它的定义:
  struct file
  {
  mode_t f_mode;/*标识文件是否可读或可写,FMODE_READ或FMODE_WRITE*/
  dev_t f_rdev; /* 用于/dev/tty */
  off_t f_pos; /* 当前文件位移 */
  unsigned short f_flags; /* 文件标志,如O_RDONLY、O_NONBLOCK和O_SYNC */
  unsigned short f_count; /* 打开的文件数目 */
  unsigned short f_reada;
  struct inode *f_inode; /*指向inode的结构指针 */
  struct file_operations *f_op;/* 文件索引指针 */
  };
  3.设备驱动程序主要组成
  (1)早期版本的字符设备注册。
  早期版本的设备注册使用函数register_chrdev(),调用该函数后就可以向系统申请主设备号,如果register_chrdev()操作成功,设备名就会出现在/proc/devices文件里。在关闭设备时,通常需要解除原先的设备注册,此时可使用函数unregister_chrdev(),此后该设备就会从/proc/devices里消失。其中主设备号和次设备号不能大于255。
  当前不少的字符设备驱动代码仍然使用这些早期版本的函数接口,但在未来内核的代码中,将不会出现这种编程接口机制。因此应该尽量使用后面讲述的编程机制。
  register_chrdev()函数格式如表11.1所示。
  表11.1 register_chrdev()函数语法要点
  所需头文件#include 《linux/fs.h》
  函数原型int register_chrdev(unsigned int major, const char *name,struct file_operations *fops)
  函数传入值major:设备驱动程序向系统申请的主设备号,如果为0则系统为此驱动程序动态地分配一个主设备号

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !