在/dev下自动创建设备节点

#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <asm/io.h>


MODULE_LICENSE("GPL");


static int major = 0;
dev_t dev;
struct cdev scull_cdev;
struct file_operations scull_fops = {
    .owner = THIS_MODULE,
    // .ioctl = scull_ioctl,
    // .open = scull_open,
    // .release = scull_close,
};
static struct class * scull_class;


// 驱动加载函数
static int hello_init(void)
{
    int result = 0;
    int err = 0;


    printk(KERN_ALERT "Hello, world\n");
    if(major){// 静态分配设备编号范围
        dev = MKDEV(major, 0);  
        result = register_chrdev_region(dev, 1, "scull0");
    }else{
        // 动态分配设备编号范围
        result = alloc_chrdev_region(&dev, 0, 1, "scull0");
        major = MAJOR(dev);
    }
    if(result < 0){
        printk(KERN_WARNING "scull: can't get major %d\n", major);
        return result;
    }
    printk("get major is %d\n", major);
    // 分配初始化struct cdev和struct file_operations
    cdev_init(&scull_cdev, &scull_fops);
    scull_cdev.owner = THIS_MODULE;
    scull_cdev.ops = &scull_fops;
    // 将设备添加到系统中
    err = cdev_add(&scull_cdev, dev, 1);
    if(err){
        printk(KERN_NOTICE "Error %d adding scull0", err);
        return -1;
    }
    // 为设备创建一个类
    scull_class = class_create(THIS_MODULE, "scull0");
    if(IS_ERR(scull_class)){
        printk(KERN_NOTICE "Error faild in creating class.\n");
        return -1;
    }
    // 创建对应设备节点
    device_create(scull_class, NULL, dev, NULL, "scull0");
    printk("scull0 install ok.\n");
    return 0;
}
static void hello_exit(void)
{
    // 从系统中移除这个字符设备
    cdev_del(&scull_cdev);
    // 删除设备节点
    device_destroy(scull_class, dev);
    // 释放设备节点类
    class_destroy(scull_class);
    // 释放设备编号
    unregister_chrdev_region(dev, 1);
    printk(KERN_ALERT "Goodbye, cruel world\n");
}


module_init(hello_init);

module_exit(hello_exit);

注意:必须启动mdev。

下面做详细介绍。

udev 和mdev 是两个使用uevent 机制处理热插拔问题的用户空间程序,两者的实现机理不同。udev 是基于netlink 机制的,它在系统启动时运行了一个deamon 程序udevd,通过监听内核发送的uevent 来执行相应的热拔插动作,包括创建/删除设备节点,加载/卸载驱动模块等等。mdev 是基于uevent_helper 机制的,它在系统启动时修改了内核中的uevnet_helper 变量(通过写/proc/sys/kernel/hotplug),值为“/sbin/mdev”。这样内核产生uevent 时会调用uevent_helper 所指的用户级程序,也就是mdev,来执行相应的热拔插动作。udev 使用的netlink 机制在有大量uevent 的场合效率高,适合用在PC 机上;而mdev 使用的uevent_helper 机制实现简单,适合用在嵌入式系统中。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设备驱动程序在`/dev`目录下创建设备文件节点,可以使用`unlink()`函数删除。具体的做法是,在驱动程序的`module_exit()`函数中调用`unlink()`函数,删除设备节点对应的设备文件。例如: ```c #include <linux/module.h> #include <linux/fs.h> #include <linux/device.h> static dev_t dev_num; // 设备号 static struct class *dev_class; // 设备类 static struct device *dev; // 设备对象 static int __init my_driver_init(void) { // 分配设备号 if (alloc_chrdev_region(&dev_num, 0, 1, "my_driver") < 0) { printk(KERN_ERR "Failed to allocate device number\n"); return -1; } // 创建设备dev_class = class_create(THIS_MODULE, "my_driver_class"); if (IS_ERR(dev_class)) { unregister_chrdev_region(dev_num, 1); printk(KERN_ERR "Failed to create device class\n"); return -1; } // 创建设备对象 dev = device_create(dev_class, NULL, dev_num, NULL, "my_device"); if (IS_ERR(dev)) { class_destroy(dev_class); unregister_chrdev_region(dev_num, 1); printk(KERN_ERR "Failed to create device object\n"); return -1; } // 其他初始化操作... return 0; } static void __exit my_driver_exit(void) { // 其他清理操作... // 删除设备对象 device_destroy(dev_class, dev_num); // 删除设备类 class_destroy(dev_class); // 释放设备号 unregister_chrdev_region(dev_num, 1); // 删除设备文件 unlink("/dev/my_device"); } module_init(my_driver_init); module_exit(my_driver_exit); ``` 在驱动程序的`module_exit()`函数中,先调用`device_destroy()`函数和`class_destroy()`函数,释放设备对象和设备类,然后调用`unregister_chrdev_region()`函数,释放设备号。最后调用`unlink()`函数,删除设备文件。需要注意的是,删除设备文件需要具有相应的权限,否则会返回错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值