Linux字符驱动中container_of宏的作用
2016-07-08 14:10
435 查看
Linux字符驱动中container_of宏的作用
首先看看这个宏的原型:
功能:根据一个结构体变量中的一个成员变量的指针来获取指向整个结构体变量的指针。
参数:
ptr:已知的结构体成员的首地址(指针);
type:要获取的结构体变量的类型
member:要获取的结构体变量中成员的名字,而不是类型
返回值:要获取的结构体变量的首地址
驱动中常用的用法,将每一个设备对应的cdev结构体和与之对应的私有成员用一个结构体封装起来:
hello_device[0]对应 设备0
hello_device[1]对应 设备1
当我们成功insmod一个设备驱动的时候,我们会通过mknod创建一个设备节点和一个具体的设备(驱动)关联,这个节点就对应这个inode结构体的一个实例,这个实例有一个struct cdev类型的字段i_cdev,它会指向hello_device中的cdev结构体(初始化cdev时候完成的)。最终获取到hello_device结构体的首地址,其cdev已经被实例化,对应一个具体的设备。
所以我们可以根据dev->cdev.dev就可以获得当前这个设备的设备号。然后包含具体设备信息的dev结构体就可以通过file中的private_data成员在open,read,write,ioctl之间传递。
在read函数中,首先根据传进来的file结构体,接收open函数传递过来的打开的具体设备的hello_device结构体,然后就可以根据这个hello_device结构体操作这个具体的设备了。
首先看看这个宏的原型:
/** * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * */ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
功能:根据一个结构体变量中的一个成员变量的指针来获取指向整个结构体变量的指针。
参数:
ptr:已知的结构体成员的首地址(指针);
type:要获取的结构体变量的类型
member:要获取的结构体变量中成员的名字,而不是类型
返回值:要获取的结构体变量的首地址
驱动中常用的用法,将每一个设备对应的cdev结构体和与之对应的私有成员用一个结构体封装起来:
struct hello_device { struct cdev cdev; char data [128]; }hello_device[NUM_OF_DEV];其中NUM_OF_DEV表示次设备的数量,假设NUM_OF_DEV为2,那么:
hello_device[0]对应 设备0
hello_device[1]对应 设备1
int hello_open(struct inode * inode,struct file * file) { struct hello_device * dev = container_of(inode->i_cdev,struct hello_device,cdev); file->private_data = dev;
... }在驱动的open函数中用container_of通过inode结构体的成员i_cdev(指向hello_device中的cdev)获取设备结构体(hello_device)的首地址,然后将获取到的hello_device结构体地址放入file结构体中在read、write函数之间传递。
当我们成功insmod一个设备驱动的时候,我们会通过mknod创建一个设备节点和一个具体的设备(驱动)关联,这个节点就对应这个inode结构体的一个实例,这个实例有一个struct cdev类型的字段i_cdev,它会指向hello_device中的cdev结构体(初始化cdev时候完成的)。最终获取到hello_device结构体的首地址,其cdev已经被实例化,对应一个具体的设备。
所以我们可以根据dev->cdev.dev就可以获得当前这个设备的设备号。然后包含具体设备信息的dev结构体就可以通过file中的private_data成员在open,read,write,ioctl之间传递。
ssize_t hello_read(struct file * file,char __user * buff,size_t count,loff_t * off) { struct hello_device * dev = file->private_data; //dev指向打开的设备结构体 copy_to_user(buff,dev->data,count);
... }
在read函数中,首先根据传进来的file结构体,接收open函数传递过来的打开的具体设备的hello_device结构体,然后就可以根据这个hello_device结构体操作这个具体的设备了。
相关文章推荐
- Linux socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程