`
bcyy
  • 浏览: 1809922 次
文章分类
社区版块
存档分类
最新评论

【内核&驱动】字符设备驱动程序【2】

 
阅读更多
一些重要的数据结构(VFS核心结构体)
1.super_block
和mount一一对应,这也意味着如果mount操作,在内核中分配新的结构体,存储分区信息
umount时,VFS就把该结构体释放掉
mount几次内核中就有几个super_block结构体

2.inode
和打开文件一一对应,记录文件信息,关闭文件时,如果内存不紧张,不会释放,
如果多个人同时打开一个文件,VFS只需创建一个inode

3.file <linux/fs.h>
和用户态对文件操作open一一对应,每次open生成一个file结构体,
内核中有多个file结构体和打开的文件对应
该结构与用户空间的FILE没有任何关联,他代表一个打开的文件,它由内核在open时创建
直到最后的close函数,在文件的所有实例都被关闭之后,内核会释放这个数据结构
指向struct file的指针称为文件指针


  1. struct file {
  2. union {
  3. struct list_headfu_list;
  4. struct rcu_head fu_rcuhead;
  5. } f_u;
  6. struct pathf_path;
  7. #define f_dentryf_path.dentry
  8. //文件对应的目录项结构
  9. #define f_vfsmntf_path.mnt
  10. const struct file_operations*f_op;
  11. atomic_long_tf_count;
  12. unsigned int f_flags;
  13. //文件标志, 如O_RDONLY, O_NONBLOCK, O_SYNC
  14. fmode_tf_mode;
  15. //文件模式
  16. loff_tf_pos;
  17. //文件当前读/写位置
  18. struct fown_structf_owner;
  19. unsigned intf_uid, f_gid;
  20. struct file_ra_statef_ra;

  21. u64f_version;
  22. #ifdef CONFIG_SECURITY
  23. void*f_security;
  24. #endif
  25. /* needed for tty driver, and maybe others */
  26. void*private_data;


  27. #ifdef CONFIG_EPOLL
  28. /* Used by fs/eventpoll.c to link all the hooks to this file */
  29. struct list_headf_ep_links;
  30. spinlock_tf_ep_lock;
  31. #endif /* #ifdef CONFIG_EPOLL */
  32. struct address_space*f_mapping;
  33. #ifdef CONFIG_DEBUG_WRITECOUNT
  34. unsigned long f_mnt_write_state;
  35. #endif
  36. };
4.file_operations <linux/fs.h>
其中包括了一组函数指针,每个打开的文件和一组函数关联起来;这些操作用于实现系统调用
file_operations和指向这类结构的指针叫做fops


  1. struct file_operations {
  2. struct module *owner;
  3. 指向拥有该结构的模块的指针,防止模块的操作在被使用的时候卸载该模块
  4. .onwer = THIS_MODULE
  5. loff_t (*llseek) (struct file *, loff_t, int);
  6. 修改文件的当前读写位置,返回新位置
  7. struct file*当前文件
  8. loff_t 长偏移量
  9. int
  10. ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
  11. 从设备中读数据
  12. ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
  13. 向设备发送数据
  14. ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
  15. 初始化一个异步读取操作
  16. ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
  17. 初始化设备上的异步写入操作
  18. int (*readdir) (struct file *, void *, filldir_t);
  19. 对设备文件来说,应该置null,用于读取目录,只对文件系统有用
  20. unsigned int (*poll) (struct file *, struct poll_table_struct *);
  21. 是poll,epoll,select的后端实现
  22. int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
  23. 提供了一种执行设备特定命令的方法
  24. long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
  25. long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
  26. int (*mmap) (struct file *, struct vm_area_struct *);
  27. 用于请求将设备内存映射到进程地址空间
  28. int (*open) (struct inode *, struct file *);
  29. 对设备文件执行的第一个操作,但不要求驱动程序一定声明该方法,
  30. 如果置为NULL,设备的打开永远有效,但系统不会通知驱动程序
  31. int (*flush) (struct file *, fl_owner_t id);
  32. 发生在进程关闭设备文件描述符副本的时候,用来执行设备上尚未完成的操作
  33. int (*release) (struct inode *, struct file *);
  34. 当file被释放时, 将调用这个操作,与open相仿,也可设置为NULL
  35. int (*fsync) (struct file *, struct dentry *, int datasync);
  36. 刷新待处理的数据
  37. int (*aio_fsync) (struct kiocb *, int datasync);
  38. fsync的异步方法
  39. int (*fasync) (int, struct file *, int);
  40. 通知设备其FASYNC状态发生了变化
  41. int (*lock) (struct file *, int, struct file_lock *);
  42. 实现文件锁
  43. ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
  44. 发送数据,每次一页
  45. unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
  46. 将底层设备中的内存段映射到进程空间的合适的位置
  47. int (*check_flags)(int);
  48. 检查传递给fcntl(F_SETFL...)调用的标志
  49. int (*dir_notify)(struct file *filp, unsigned long arg);
  50. int (*flock) (struct file *, int, struct file_lock *);
  51. ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
  52. ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
  53. int (*setlease)(struct file *, long, struct file_lock **);
  54. };
file_operations的初始化方式

  1. struct file_operations scull_fops = {
  2. .owner = THIS_MODULE,
  3. .llseek = scull_llseek,
  4. .read = scull_read,
  5. .write = scull_write,
  6. .ioctl = scull_ioctl,
  7. .open = scull_open,
  8. .release = scull_release,
  9. };
字符设备的注册
在运行的时候获得一个独立的cdev结构:

  1. struct cdev *my_cdev = cdev_alloc();
  2. my_cdev->ops = &my_fops;
此时就可以将cdev结构嵌入到自己的设备的特定结构中
以下代码用来初始化已分配到的结构:

  1. void cdev_init(struct cdev *cdev, struct file_operations *fops);
通过以下代码告知内核结构的信息:

  1. int cdev_add(struct cdev *dev, dev_t num, unsigned int count);

dev 是cdev结构
num 是该设备对应的第一设备编号
count 是应该和该设备关联的设备号的数量

scull中的设备注册
在scull内部, 他通过struct scull_dev的结构来表示每个设备


  1. struct scull_dev {
  2. struct scull_qset *data;/* 指向第一个量子集的指针 */
  3. int quantum;/* 当前量子的大小 */
  4. int qset;/* 当前数组的大小 */
  5. unsigned long size;/* 保存在其中的数据总量 */
  6. unsigned int access_key;/* 由sculluid和scullpriv使用 */
  7. struct semaphore sem;/* 互斥信号量 */
  8. struct cdev cdev/* 字符设备结构 */
  9. };
量子:我们把每一个内存区域称之为量子,一个指向这些量子的指针数组称之为量子集

  1. static void scull_setup_cdev(struct scull_dev *dev, int index)
  2. {
  3. int err, devno;
  4. devno = MKDEV(scull_major, scull_minor index);

  5. cdev_init(&dev->sdev, &scull_fops);
  6. dev->cdev.owner = THIS_MODULE;
  7. dev->cdev.ops = &scull_fops;

  8. err = cdev_add(&dev->cdev, devno, 1);
  9. if (err) {
  10. printk(KERN_NOTICE "Error %d adding scull%d", err, index);
  11. }
  12. }

早期办法(内核2.6之前的版本的设备注册的方法)

注册:

  1. int register_chrdev(unsigned int major,
  2. const char * name,
  3. struct file_operations *fops);


释放:

  1. int unregister_chrdev(unsigned int major, const char * name);





分享到:
评论

相关推荐

    深入linux设备驱动程序内核机制

    深入linux设备驱动程序内核机制 pdf深入linux设备驱动程序内核机制深入linux设备驱动程序内核机制深入linux设备驱动程序内核机制深入linux设备驱动程序内核机制深入linux设备驱动程序内核机制深入linux设备驱动程序...

    linux字符设备驱动程序

    “mydriver”的简单字符设备驱动程序,该驱动程序以可加载的模块方式进行编译,这样可以免去重新编译内核的工作。

    深入Linux设备驱动程序内核机制.pdf

    本文深入探讨了Linux设备驱动程序的内核机制,并提供了一个简单的字符设备驱动程序示例。通过源码示例,详细讲解了驱动程序注册与注销、文件操作函数的实现、设备号分配等关键概念和操作方法。 通过学习本文,您将...

    Linux内核和设备驱动程序实验报告

    Linux内核和设备驱动程序实验报告

    基于Linux字符设备驱动程序的设计与实现

    Linux 设备驱动程序是为特定的硬件提供给用户程序的 一组标准化接口,它隐藏了设备工作的细节。Linux 系统下 驱动程序是运行在内核态的,是和内核连接在一起的程序。 如果运行在用户态的应用程序想控制硬件设备,...

    linux字符设备驱动实例

    本例子是一个linux字符设备驱动的最简单的例子,有详细的说明,适合初次接触者。

    Linux内核与设备驱动程序学习资料笔记+源码.zip

    Linux内核与设备驱动程序学习资料笔记+源码.zipLinux内核与设备驱动程序学习资料笔记+源码.zipLinux内核与设备驱动程序学习资料笔记+源码.zipLinux内核与设备驱动程序学习资料笔记+源码.zipLinux内核与设备驱动程序...

    linux字符设备驱动程序学习笔记

    详细介绍了linux字符设备驱动程序,对各个名词做了自己的理解,在学习中的笔记,有错误还请海涵

    linux 字符设备驱动程序 示例代码

    linux字符设备驱动程序,示例代码。 共8个文件。包括内核态的驱动程序和用户态的测试例程。

    字符设备驱动.doc

    字符设备驱动程序开发流程 设备号 字符设备驱动的重要数据结构介绍 字符设备的注册流程 字符设备相关操作 创建设备文件 编写驱动程序程序 主设备号 –前12位 表示与设备文件相关联的驱动程序 确定设备类型 ...

    Linux 内核分析与驱动编程

    进程管理与调度 Lecture3:中断处理、系统调用 Lecture4:内核同步 Lecture5:内存管理(1) Lecture6:内存管理(2) Lecture7 :文件系统 Lecture8:内核设备模型、时钟管理、设备I/O、PCI设备驱动程序 ...

    Linux简单的字符设备驱动程序

    基于linux2.4内核版本的字符设备驱动,适合作为操作系统课程设计。其中包含了测试文件与makefile文件。

    Linux设备驱动程序开发基础(PPT)

    Linux设备驱动程序开发简介 Linux设备驱动程序结构 Linux设备驱动程序加载方式 实验:编写一个字符设备驱动程序(LED或蜂鸣器) 分别用静态编译,模块动态加载方法实现加入内核

    基于linux2.6内核的字符设备驱动程序设计.pdf

    基于linux2.6内核的字符设备驱动程序设计.pdf

    深入Linux设备驱动程序内核机制

    深入Linux设备驱动程序内核机制 知道好的下吧

    linux字符设备驱动

    1)编写一个简单的字符设备驱动程序,该字符设备包括打开、读、写、I/O控制与释放五个基本操作。...2)编写一个测试程序,测试字符设备驱动程序的正确性。 3)要求在实验报告中列出Linux内核的版本与内核加载的过程

    Linux内核与设备驱动程序学习笔记及源码.zip

    Linux内核与设备驱动程序学习笔记及源码.zip Linux内核与设备驱动程序学习笔记及源码.zip Linux内核与设备驱动程序学习笔记及源码.zip Linux内核与设备驱动程序学习笔记及源码.zip Linux内核与设备驱动程序学习笔记...

    精通LINUX设备驱动程序开发

     第5章 字符设备驱动程序   第6章 串行设备驱动程序   第7章 输入设备驱动程序   第8章 I2C协议  第9章 PCMCIA和CF   第10章 PCI   第11章 USB  第12章 视频驱动程序   第13章 音频驱动程序...

    精通Linux设备驱动程序开发

    第5章 字符设备驱动程序 第6章 串行设备驱动程序 第7章 输入设备驱动程序 第8章 I2C协议 第9章 PCMCIA和CF 第10章 PCI 第11章 USB 第12章 视频驱动程序 第13章 音频驱动程序 第14章 块设备驱动程序 第15章...

Global site tag (gtag.js) - Google Analytics