一个globalmem驱动的3个问题
书中的一个经典的有关字符设备驱动的例子,有些困惑
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
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是静态分配的~ 在编译程序的以后就预留了内存空间~
mem只是内存的大小啊,起始地址不设定的话,怎么read和write啊??
那么这片内存的分配就是编译器自动分配的??
[ 本帖最后由 todayrw 于 2009-4-14 17:15 编辑 ]
起始地址由编译器设定吧~
read的话看这里
copy_to_user(buf, (void*)(dev->mem + p), count))
dev->mem就是起始地址, p 就是偏移地址~
总算明白了,看漏了,前面有动态分配内存: globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
另外,还有重要的一点:
File结构代表一个打开的文件,系统中每个打开的文件,在内核空间都对应一个file结构。它由内核在调用open时创建,并传递给在该文件上操作的所有函数,直到最后的close函数。在文件的所有实例都被关闭以后,内核才会释放这个结构。
就是说open中驱动给内核file,然后在read和write中,再由内核file传递给局部变量进行后续操作。
在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指向设备结构体就可以
对!我也才想到,兄弟,本来有一半分应该给你的。谢谢啊!