您的位置:首页 > 运维架构 > Linux

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

2015-07-02 15:12 811 查看
#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 机制实现简单,适合用在嵌入式系统中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LINUX driver dev