当前位置:首页>Linux>linux驱动节点的创建

linux驱动节点的创建

  • 2026-09-02 16:52:38
linux驱动节点的创建

在Linux驱动开发中,设备节点是用户空间与内核空间交互的重要接口。以下介绍如何通过代码实现自动生成设备节点

方法一:使用杂项设备(Misc Device)

杂项设备是一种简化的字符设备,适合快速实现设备节点。

1 步骤

定义文件操作函数 定义open、release和ioctl等操作函数
static int device_open(structi node *inode,struct file *file) {
    printk(KERN_INFO"Device opened\n");
    return0;
}
static int device_release(struct inode *inode,struct file *file) {
    printk(KERN_INFO"Device closed\n");
    return0;
}
static long device_ioctl(struct file *file,unsigned int cmd,unsigned long arg) {
    printk(KERN_INFO"IOCTL called\n");
    return0;
}
static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = device_open,
    .release = device_release,
    .unlocked_ioctl = device_ioctl,
};

注册杂项设备使用miscdevice结构体注册设备:

static struct miscdevice my_device = {
.minor = MISC_DYNAMIC_MINOR,
.name ="my_device",
.fops = &fops,
};
static int__init my_driver_init(void) {
misc_register(&my_device);//注册名称为my_device的设备节点
printk(KERN_INFO"Device registered\n");
return0;
}
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_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
方法二 device_create_file用于在sys下创建设备的属性节点

在platform总线的驱动中创建节点

代码示例:

//节点的读函数

static ssize_t demo_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
    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);
    int ret, val;
    ret = kstrtoint(buf, 10, &val);
    if (ret)
    return ret;
    priv->value = val;
    dev_info(dev, "value set to %d\n", val);
    return count;
}
/* 使用 DEVICE_ATTR 宏定义属性 */
static DEVICE_ATTR_RW(demo); // 生成 dev_attr_demo,确定节点的权限,可读可写
static int my_probe(struct platform_device *pdev)
{
    struct my_priv *priv;
    int ret;
    dev_info(&pdev->dev, "probe enter\n");
    /* 1. 分配私有数据 */
    priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
    if (!priv)
        return -ENOMEM;
    priv->value = 100;
    priv->enable = 1;
    /* 2. 保存私有数据 */
    platform_set_drvdata(pdev, priv);
    /* 3. 创建 sysfs 节点 ,节点名为demo*/
    ret = device_create_file(&pdev->dev, &dev_attr_demo);
    if (ret) {
            dev_err(&pdev->dev, "failed to create value file\n");
        return ret;
     }
    return 0;
}
static int my_remove(struct platform_device *pdev)
{
    dev_info(&pdev->dev, "remove enter\n");
    /* 必须按创建的逆序删除 */
    device_remove_file(&pdev->dev, &dev_attr_value);
    return 0;
}
/* ========== 驱动注册 ========== */
static struct platform_device *my_pdev;
static struct platform_driver my_driver = {
    .probe = my_probe,
    .remove = my_remove,
    .driver = {
    .name = "my-dev",
    },
};
static int __init my_init(void)
{
    int ret;
    /* 注册驱动 */
    ret = platform_driver_register(&my_driver);
    if (ret)
    return ret;
    /* 创建 platform 设备(模拟设备树中没有节点的情况) */
    my_pdev = platform_device_alloc("my-dev", 0);
    if (!my_pdev) {
    platform_driver_unregister(&my_driver);
    return -ENOMEM;
    }
    ret = platform_device_add(my_pdev);
    if (ret) {
    platform_device_put(my_pdev);
    platform_driver_unregister(&my_driver);
    return ret;
    }
return 0;
}
static void __exit my_exit(void)
{
    platform_device_unregister(my_pdev);
    platform_driver_unregister(&my_driver);
}
module_init(my_init);
module_exit(my_exit);
MODULE_AUTHOR("Example");
MODULE_DESCRIPTION("device_create_file example");
MODULE_LICENSE("GPL");
方法三、使用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[] = {
    &dev_attr_demo1.attr,
    &dev_attr_demo2.attr,
    &dev_attr_demo3.attr,
    NULL, //这里必须要以NULL结尾
}; //末尾有分号

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[] = {
    &dev_attr_demo1.attr,
    &dev_attr_demo2.attr,
    &dev_attr_demo3.attr,
NULL, //这里必须要以NULL结尾
}; //末尾有分号
static const struct attribute_group demo_attr_grp = {
    .attrs = demo_attrs,
}
static int __devinit demo_probe(struct platform_device *pdev)
{
int ret = 0;
/* led gpio init. */
..................
ret = sysfs_create_group(&pdev->dev.kobj,&demo_attr_grp);
//创建节点名为demo1 demo2 demo3 的3个节点
if (ret)
return ret;
return 0;
}
#在用户层可以使用ioctl调用到节点的ioctl函数中,可以用wirte和read调用到节点的读写函数

最新文章

随机文章