在Linux驱动开发中,设备节点是用户空间与内核空间交互的重要接口。以下介绍如何通过代码实现自动生成设备节点
方法一:使用杂项设备(Misc Device)
杂项设备是一种简化的字符设备,适合快速实现设备节点。1 步骤
定义文件操作函数 定义open、release和ioctl等操作函数static int device_open(structi node *inode,struct file *file) { printk(KERN_INFO"Device opened\n");static int device_release(struct inode *inode,struct file *file) { printk(KERN_INFO"Device closed\n");static long device_ioctl(struct file *file,unsigned int cmd,unsigned long arg) { printk(KERN_INFO"IOCTL called\n");static struct file_operations fops = { .release = device_release, .unlocked_ioctl = device_ioctl,注册杂项设备使用miscdevice结构体注册设备:
static struct miscdevice my_device = {.minor = MISC_DYNAMIC_MINOR,static int__init my_driver_init(void) {misc_register(&my_device);//注册名称为my_device的设备节点printk(KERN_INFO"Device registered\n");static void__exit my_driver_exit(void) {misc_deregister(&my_device);//卸载节点printk(KERN_INFO"Device unregistered\n");module_init(my_driver_init);module_exit(my_driver_exit);MODULE_AUTHOR("Your Name");方法二 device_create_file用于在sys下创建设备的属性节点在platform总线的驱动中创建节点
代码示例:
//节点的读函数
static ssize_t demo_show(struct device *dev,struct device_attribute *attr, struct my_priv *priv = dev_get_drvdata(dev); return sprintf(buf, "%d\n", priv->value);static ssize_t demo_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t count) struct my_priv *priv = dev_get_drvdata(dev); ret = kstrtoint(buf, 10, &val); dev_info(dev, "value set to %d\n", val);/* 使用 DEVICE_ATTR 宏定义属性 */static DEVICE_ATTR_RW(demo); // 生成 dev_attr_demo,确定节点的权限,可读可写static int my_probe(struct platform_device *pdev) dev_info(&pdev->dev, "probe enter\n"); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); platform_set_drvdata(pdev, priv); /* 3. 创建 sysfs 节点 ,节点名为demo*/ ret = device_create_file(&pdev->dev, &dev_attr_demo); dev_err(&pdev->dev, "failed to create value file\n");static int my_remove(struct platform_device *pdev) dev_info(&pdev->dev, "remove enter\n"); device_remove_file(&pdev->dev, &dev_attr_value);/* ========== 驱动注册 ========== */static struct platform_device *my_pdev;static struct platform_driver my_driver = {static int __init my_init(void) ret = platform_driver_register(&my_driver); /* 创建 platform 设备(模拟设备树中没有节点的情况) */ my_pdev = platform_device_alloc("my-dev", 0); platform_driver_unregister(&my_driver); ret = platform_device_add(my_pdev); platform_device_put(my_pdev); platform_driver_unregister(&my_driver);static void __exit my_exit(void) platform_device_unregister(my_pdev); platform_driver_unregister(&my_driver);MODULE_AUTHOR("Example");MODULE_DESCRIPTION("device_create_file example");方法三、使用sysfs_create_group创建多个节点sysfs_create_group可以用于一次创建多个属性节点
1. 初始化device_attribute
这里创建多个节点
static DEVICE_ATTR(demo1, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);
static DEVICE_ATTR(demo2, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);
static DEVICE_ATTR(demo3, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);
2. 定义属性结构体数组
static struct attribute *demo_attrs[] = {3. 定义attribute属性结构体数组到属性组中
static const struct attribute_group demo_attr_grp = {
.attrs = demo_attrs,
}
4. 创建sysfs接口
sysfs_create_group(&pdev->dev.kobj,&dev_attr_led);5. 代码示例:
static DEVICE_ATTR(demo1, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);static DEVICE_ATTR(demo2, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);static DEVICE_ATTR(demo3, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);static struct attribute *demo_attrs[] = {static const struct attribute_group demo_attr_grp = {static int __devinit demo_probe(struct platform_device *pdev)ret = sysfs_create_group(&pdev->dev.kobj,&demo_attr_grp);//创建节点名为demo1 demo2 demo3 的3个节点