免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3252 | 回复: 6
打印 上一主题 下一主题

一个globalmem驱动的3个问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-14 16:23 |只看该作者 |倒序浏览
10可用积分
书中的一个经典的有关字符设备驱动的例子,有些困惑

struct globalmem_dev                                    
{                                                        
  struct cdev cdev; /*cdev结构体*/                       
  unsigned char mem[GLOBALMEM_SIZE]; /*全局内存*/        
};

struct globalmem_dev *globalmem_devp; /*设备结构体指针*/   //指针变量globalmem_devp并未赋值,所以它暂时是乱指向的

/*文件打开函数*/
int globalmem_open(struct inode *inode, struct file *filp)
{
  /*将设备结构体指针赋值给文件私有数据指针*/
  filp->private_data = globalmem_devp;        //问题1:globalmem_devp没有确定地址,怎么能给其它变量赋值??
  return 0;
}

/*读函数*/
static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size,
  loff_t *ppos)
{
  unsigned long p =  *ppos;
  unsigned int count = size;
  int ret = 0;
  struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/  //问题2:在globalmem_open()函数中,filp->private_data是被赋值的,到了这里的read函数,怎么变成赋值给局部变量了??

  /*分析和获取有效的写长度*/
  if (p >= GLOBALMEM_SIZE)
    return count ?  - ENXIO: 0;
  if (count > GLOBALMEM_SIZE - p)
    count = GLOBALMEM_SIZE - p;

  /*内核空间->用户空间*/
  if (copy_to_user(buf, (void*)(dev->mem + p), count))
  {
    ret =  - EFAULT;
  }
  else
  {
    *ppos += count;
    ret = count;
   
    printk(KERN_INFO "read %d bytes(s) from %d\n", count, p);
  }

  return ret;
}

书上说:"在globalmem_open()函数中通过filp->private_data = globalmem_devp语句将设备结构体指针赋值给文件私有数据指针"

"在globalmem_read() 、globalmem_write()、globalmem_llseek()和globalmem_ioctl()函数中通过

struct globalmem_dev *dev = filp->private_data语句获得设备结构体指针"


问题3:我理解:这个驱动的功能是使用户空间能够访问内核空间的一片内存(大小有设定),可是,为什么从程序上看不出这片内存的起始地址??谁设定的??

[ 本帖最后由 todayrw 于 2009-4-14 16:45 编辑 ]

最佳答案

查看完整内容

globalmem_devp是一个指针,指向globalmem_dev这个指针是存在的,但是它所指的globalmem_dev结构是空的~ 也就是说这个指针还没有指向一个globalmem_dev 结构然后filp的private_data是一个void类型的指针,它指向了globalmem_devp这个指针然后在struct globalmem_dev *dev = filp->private_data;中dev这个指针所指的globalmem_dev结构其实就是globalmem_devp所指的globalmem_dev结构这个结构的主要内存就是struct globalmem_dev ...

论坛徽章:
0
2 [报告]
发表于 2009-04-14 16:23 |只看该作者
globalmem_devp是一个指针,指向globalmem_dev
这个指针是存在的,但是它所指的globalmem_dev结构是空的~ 也就是说这个指针还没有指向一个globalmem_dev 结构

然后filp的private_data是一个void类型的指针,它指向了globalmem_devp这个指针

然后在
struct globalmem_dev *dev = filp->private_data;

dev这个指针所指的globalmem_dev结构其实就是globalmem_devp所指的globalmem_dev结构


这个结构的主要内存就是
struct globalmem_dev                                    
{                                                        
  struct cdev cdev; /*cdev结构体*/                       
  unsigned char mem[GLOBALMEM_SIZE]; /*全局内存*/        
};
中的mem吧~  这个mem是静态分配的~  在编译程序的以后就预留了内存空间~

论坛徽章:
0
3 [报告]
发表于 2009-04-14 17:13 |只看该作者

回复 #2 superfight 的帖子

mem只是内存的大小啊,起始地址不设定的话,怎么read和write啊??
那么这片内存的分配就是编译器自动分配的??

[ 本帖最后由 todayrw 于 2009-4-14 17:15 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2009-04-14 17:18 |只看该作者
起始地址由编译器设定吧~

read的话看这里

copy_to_user(buf, (void*)(dev->mem + p), count))

dev->mem就是起始地址, p 就是偏移地址~

论坛徽章:
0
5 [报告]
发表于 2009-04-14 17:22 |只看该作者

回复

总算明白了,看漏了,前面有动态分配内存: globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);

另外,还有重要的一点:
File结构代表一个打开的文件,系统中每个打开的文件,在内核空间都对应一个file结构。它由内核在调用open时创建,并传递给在该文件上操作的所有函数,直到最后的close函数。在文件的所有实例都被关闭以后,内核才会释放这个结构。

就是说open中驱动给内核file,然后在read和write中,再由内核file传递给局部变量进行后续操作。

论坛徽章:
0
6 [报告]
发表于 2009-04-14 17:27 |只看该作者
在kmalloc函数中为其分配了地址,具体看一下init函数
程序执行是先init,然后才是open、read、write和lseek
也就是说
在init执行时, globalmem_devp已经获得了地址空间,然后在open函数中才将此地址空间传递给filp->private_data ,这样在read、write和lseek的时候可以通过filp->private_data 获得地址空间
其实没有filp->private_data 也可以,只需把globalmem_devp指向设备结构体就可以

论坛徽章:
0
7 [报告]
发表于 2009-04-14 17:47 |只看该作者

回复 #6 zhongfrank 的帖子

对!我也才想到,兄弟,本来有一半分应该给你的。谢谢啊!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP