Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4238155
  • 博文数量: 1148
  • 博客积分: 25453
  • 博客等级: 上将
  • 技术积分: 11949
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-06 21:14
文章分类

全部博文(1148)

文章存档

2012年(15)

2011年(1078)

2010年(58)

分类: LINUX

2011-12-18 21:47:21

本文的copyright归yuweixian4230@163.com 所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:yuweixian4230@163.com
博客:
yuweixian4230.blog.chinaunix.net  

本节对“从globalmem学习linux字符设备驱动”中,关于file_operations的 read
函数进行学习。


该函数创造一个新的文件对象 struct file * filp,并将他和相应的索引节点*inodep,对象关联起来。由系统调用open()调用它。
1. 如果设备是第一次打开,则对其进行初始化。
2. 如果必要,更新 *flip指针。
3. 分配并填写置于flip->private_data里的数据结构。

函数原型:
  1. int (*open) (struct inode *, struct file *);
  1. 简单介绍
  2. struct inode{
  3. dev_t i_dev;
  4. struct cdev *i_dev;
  5. };

  6. struct file{
  7. const struct file_operations *f_op;
  8. void *private_data;
  9. fmode_t fmode;//00666  在open系统调用时,会获取这些属性
  10. unsigned int flags;//只读
  11. };


将设备结构体指针赋值给文件私有数据指针

原型如下:
  1. src/include/linux/kernle.h 2.6.35

  2. 715/**
  3.  716 * container_of - cast a member of a structure out to the containing structure
  4.  717 * @ptr: the pointer to the member.
  5.  718 * @type: the type of the container struct this is embedded in.
  6.  719 * @member: the name of the member within the struct.
  7.  720 *
  8.  721 */
  9.  722 #define container_of(ptr, type, member) ({ \
  10.  723 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
  11.  724 (type *)( (char *)__mptr - offsetof(type,member) );})
在ldd3 p62中这么使用,
  1. struct scull_dev{
  2. struct cdev cdev;
  3. int qset;
  4. };
  5. open函数中: 通过inode结构体,返回 struct scull_dev 结构体指针
  6. struct scull_dev *dev;
  7. dev = container_of(inode->i_cdev,struct scull_dev,cdev);
  8. flip->private_data = dev;
在linux设备驱动详解 p131
  1. struct globalmem_dev *globalmem_devp;

  2. int globalmem_open(struct inode *inode,struct file *flip)
  3. {
  4. //将设备结构体指针赋值给问价私有数据指针
  5. flip->private_data = globalmem_devmp;
  6. return 0;
  7. }
其实,不提倡用上述直接调用全局变量 struct globalmem_dev *globalmem_devp;
这样会导致混乱,使用 contain_of 函数,如下使用
在linux设备驱动详解2 p135
  1. int globalmem_open(struct inode *inode,struct file *flip)
  2. {
  3. struct globalmem_dev *dev;
  4. dev = conainer_of(inode->cdev,struct globalmem_dev,cdev);
  5. flip->private_data = dev;
  6. return 0;
  7. }

在内核源码中的一些例子
============================
  1. src/drivers/char/efirtc.c

  2.  264static int efi_rtc_open(struct inode *inode, struct file *file)
  3.  265{
  4.  266 /*
  5.  267 * nothing special to do here
  6.  268 * We do accept multiple open files at the same time as we
  7.  269 * synchronize on the per call operation.
  8.  270 */
  9.  271 return 0;
  10.  272}
  11. 在同一个时刻,每次系统调用时,我们允许打开多个文件

============================================

我是这么认为:
系统调用open("test.txt",O_RDWR,00700);打开一个文件时,file结构体在内核中产生一个文件对象,系统调用open则返回一个文件描述符。file结构体则获得了该文件操作的属性 O_RDWR,00700等。

当有两个open系统调用时,第一次系统调用,open驱动程序产生struct inode结构体和struct file 结构体file1,当第二次系统调用时,open驱动程序再次产生struct file结构体file1。而且这两个file结构体对象都指向索引inode。为了能在内核中分开操作file,我们需要在内核open函数中,将设备结构体指针赋值给文件私有数据指针
  1. struct globalmem_dev *dev;
  2. dev = conainer_of(inode->cdev,struct globalmem_dev,cdev);
  3. flip->private_data = dev;

linux设备驱动开发及应用 p127 
linux内核可支持多进程。多个进程可同时使用一个设备驱动程序。因此,设计设备驱动程序时要考虑到这一点。由于要分别管理使用同一个设备驱动程序的多个进程,因此,按进程分类方法分配和初始化内存。通常,在文件结构体的flip的private_data上注册、管理和使用按进程分类管的内存。
flip->private_data =vmalloc(1024);


阅读(6251) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~