在open函数中将文件私有数据指向设备结构体

本文探讨了在Linux设备驱动中实现open函数的重要性。字符设备的open接口是必需的,因为它使得操作文件成为可能。open函数用于找到设备的file_operations,同时也为后续的read、write和ioctl等操作提供了设备结构体的访问。不实现open函数虽然可以工作,但不推荐,因为它是标准化操作的一部分。文中通过例子展示了如何在open函数中将文件的private_data指向设备结构体,以便在其他驱动函数中方便地访问设备数据。
摘要由CSDN通过智能技术生成

引子:

在jz2440韦东山写的led驱动,并没有实现open函数。在测试app中,仍使用

open(filename, O_RDWR)打开设备并随后对其进行ioctl以及read等操作。

【App中filename = "/dev/leds" 或"/dev/led1" "/dev/led2" "/dev/led3"】

而在《linux设备驱动开发详解》中的一个驱动,实现了open。

  1. int xx_open(struct inode inode ,struct file* filp)
  2. {
  3.     struct xx_dev *dev;
  4.     dev = container_of(inode->i_cdev , struct xx_dev ,cdev);
  5.     filp->private_data = dev ;
  6.     return 0;
  7. }

那么,open实现与否有何影响?

_______________________________________________________________________________

  1. QQ 潘老师 12:45:31
  2. 字符设备框架中open接口是必须实现的
  3. 原因如下:
  4. 1、一切皆是"文件",字符设备也是"文件"
  5. 2、要操作一个文件必须先open,才能read/write
  6. 字符设备的原理如下:
  7. 1、cdev表征一个字符设备对象
  8. 通过cdev_alloc构造,cdev_init初始化好
  9. 然后用cdev_add把这个对象插入内核管理数据区(链表,插入节点)
  10. 2、mknod创建设备文件
  11. 就是在VFS树形结构中创建了一个节点inode
  12. inode根据类型,字符设备的默认open方法仅仅查找cdev对象节点
  13. 3、open过程
  14. open通过设备文件查找到inode,并回调inode中的默认打开方面找到cdev对象,这样就找到了cdev中封装的file_operations,即操作方法函数集合,同时open过程会创建一个file对象(原因是open的时候有标志:譬如只读、只写、阻塞等等,两次打开的时候标志可以不一致,则每次创建一个file对象来抽象"文件",实际就是存储这些标志,并保存指向cdev中保存的file_operations方法)
  15. 4、read/write过程
  16. 通过文件描述符找到open时创建的file对象,就找到了open时初始化好的file中指向file_operations,则找到了驱动中对应的操作函数

 

  1. 百度知道Wu_Roc
  2. 如果不实现open的话,驱动会默认设备的打开永远成功。打开成功时open返回0。
  3. 内核里是若open函数未定义的话,会跳过这个函数。但是其他步骤不变。
  4. 关键代码:__dentry_open函数里
  5. ...
  6. if (open) {
  7.     error = open(inode, f);
  8.     if (error)
  9.         goto cleanup_all;
  10. }
  11. ...
  12. 所以sys_open调用的话会依旧照常进行。如果你定义了open,他就会调用的你写的open,如果没定义,就跳过这一步。
  13. 这里说明不实现open是允许的。

经过多方对比参考,在下面这个文章找到了想要的答案:

http://blog.sina.com.cn/s/blog_95268f5001015bkd.html

大多数linux驱动工程师都遵循一个"潜规则",那就是将文件的私有的数据private_data指向设备结构体,在read(),write,ioctl(),llseek等函数通过private_data访问设备结构体。一般,我们在open里,讲设备结构体赋值给文件私有数据指针,然后我们在ioctlreadwrite等函数里面,通过filep找到设备结构体,并对设备进行操作。代码如下:

  1. struct globalmem_dev{
  2.  struct cdev cdev;//cdev结构体,用于描述设备的结构体
  3.  unsigned char mem[GLOBALMEM_SIZE];//全局内存
  4. };//自定义设备结构体
  5. struct globalmem_dev *globalmem_devp;//指向设备的结构体指针
  6. int globalmem_open(struct inode *inode,struct file *filp)
  7. {
  8. filp->private_data = globalmem_devp;//将设备结构体指针赋给文件私有数据指针,也就是将文件的私有的数据private_data指向设备结构体
  9. return 0;
  10. }
  11. //设备控制函数
  12. static int globalmem_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd,unsigned longarg)
  13. {
  14.   struct globalmem_dev *dev = filp->private_data;//获得设备结构体指针
  15. switch (cmd) {
  16.  case MEM_CLEAR :
  17.   memset(dev->mem,0,GLOBALMEM_SIZE);//清除全局内存
  18.   printk(KERN_INFO "globalmem is set to zero\n");
  19.   break;
  20.  
  21.  default :
  22.    return -EINVAL;
  23. }
  24. return 0;
  25. }

从中可以看出,open的实现结合readwrite,实现了一种规范化的操作。在用户程序中,我们通过filename找到设备的inode或者filep,然后找到设备【具体过程不清楚】,并对其进行读写和控制。【待补充】

{

10.21:

struct globalmem_dev *dev = filp->private_data;

可以通过MINOR(dev->cdev->devno)得到minor,再switch(minor){ casexx : .....},这样似乎是在韦东山的代码上加了一层封装。

 }

 

而在韦东山的代码中,因为没有实现open,使用了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值