一个globalmem驱动的3个问题

发布于 2022-09-18 18:19:27 字数 3036 浏览 18 评论 0

书中的一个经典的有关字符设备驱动的例子,有些困惑

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 编辑 ]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

心在旅行 2022-09-25 18:19:27

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是静态分配的~  在编译程序的以后就预留了内存空间~

打小就很酷 2022-09-25 18:19:27

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

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

贩梦商人 2022-09-25 18:19:27

起始地址由编译器设定吧~

read的话看这里

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

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

爱,才寂寞 2022-09-25 18:19:27

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

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

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

执着的年纪 2022-09-25 18:19: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指向设备结构体就可以

耀眼的星火 2022-09-25 18:19:27

对!我也才想到,兄弟,本来有一半分应该给你的。谢谢啊!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文