device_attribute 主要用于在sys子系统中,用户空间与内核空间的交互,在这里采用device_attribute 将版本信息输出到sys子系统中。用户空间用cat指令即可查看。有两种方式:
1、创建字符设备
使用device_create创建设备文件,返回值是struct device结构体类型的mydevice,然后使用device_create_file创建xxxinfo我文件,参数就是前面创建设备文件的返回值mydevice,和自己定义的device_attribute 结构体变量xxxinfo,这样就会生成/sys/devices/virtual/xxx/yyy/xxxinfo文件,在终端使用cat命令查看就能看到通过xxxinfo_show中sprintf打印出的信息。
//device_attribute 结构体中重要俩个函数 这里只用了.show .attr包括模式和名字
static struct device_attribute xxxinfo = {
.attr = {
.name = "xxxinfo",
.mode = 0444,
},
.show = xxxinfo_show,
};
char *drv_info = "I am xxx.ko";
在drvinfo_show中采用sprintf()直接将信息输出。用户层利用cat就可获取数据信息
static ssize_t xxxinfo_show(struct device *dev,struct device_attribute * attr,char * buf)
{
return sprintf(buf,"driver info is %s\r\n", drv_info );
}
//在sys子系统下Class目录下创建一个XXX目录,一般在驱动中的probe函数中进行
myclass = class_create(THIS_MODULE, "XXX");
if(IS_ERR(myclass))
{
printk("XXX class_create error\n");
return 0;
}
//在XXX目录下创建一个yyy目录
mydevice=device_create(myclass, NULL, chrdev_no, NULL, "yyy");
//在yyy目录下创建xxxinfo节点,通过读取节点即可获取信息版本
if(device_create_file(mydevice, &drvinfo))
printk(KERN_ALERT "Unable to create sysfs entry: '%s'\n",drvinfo.attr.name);
else
printk(KERN_ALERT "create sysfs file success\r\n");
//最后在disconnect函数中使用device_remove_file删除
device_remove_file(mydevice, &xxxinfo);
2、使用子系统的框架
不用创建字符设备框架,使用子系统的框架,例如input子系统,usb子系统,这些子系统内部会自动生成字符设备,只不过这些子系统的主设备号都是固定的。这里以usb子系统为例,使用usb_register_dev创建一个usb设备,这样创建的usb设备的主设备号全部都是180,次设备号自己通过参数usb_class_driver结构体的minor_base成员传递进去。
//device_attribute 结构体中重要俩个函数 这里只用了.show .attr包括模式和名字
static struct device_attribute xxxinfo = {
.attr = {
.name = "xxxinfo",
.mode = 0444,
},
.show = xxxinfo_show,
};
char *drv_info = "I am xxx.ko";
在drvinfo_show中采用sprintf()直接将信息输出。用户层利用cat就可获取数据信息
static ssize_t xxxinfo_show(struct device *dev,struct device_attribute * attr,char * buf)
{
return sprintf(buf,"driver info is %s\r\n", drv_info );
}
struct file_operations xxx_fops = {
.owner = THIS_MODULE,
.open = xxx_open,
.release=xxx_release,
.read = xxx_read,
.write = xxx_write,
};
static struct usb_class_driver usb_xxx_class = {
.name = "usb_xxx", /* 设备的名称,该名称将出现在sysfs文件系统中 */
.fops = &xxx_fops , /* 字符设备的函数操作指针 */
.minor_base = 193, /* 设备驱动的次编号,当作为字符设备的时候主编号固定为180 */
};
//probe函数中
struct usb_device *dev = interface_to_usbdev(intf); /* 由接口获得usb_device */
retval = usb_register_dev(intf, &usb_xxx_class); /* 注册一个 USB 设备,并要求一个次设备号 */
if (retval) {
printk(KERN_ALERT "register usb device error!\n");
goto fail5;
}
//dev上面通过probe函数参数intf得到的usb_interface结构体,可以得到usb设备的usb_device 结构体,而usb_device 结构体的dev成员就有struct device *dev,这样&dev->dev就是获得使用usb_register_dev创建的设备文件的struct device结构体,作为device_create_file的第一个参数
if(device_create_file(&dev->dev, &xxxinfo))
printk(KERN_ALERT "Unable to create sysfs entry: '%s'\n",xxxinfo.attr.name);
else
printk(KERN_ALERT "create sysfs file success\r\n");
//最后在disconnect函数中使用device_remove_file删除
struct usb_device *dev = interface_to_usbdev(intf); /* 由接口获得usb_device */
device_remove_file(&dev->dev, &xxxinfo);
可以使用find / -name xxxinfo查看这个文件在那个目录下,并用cat命令查看