Linux文字デバイスドライバ自動作成デバイスノード

8424 ワード

Linuxはudev、mdevのメカニズムを使用してデバイスノードを自動的に作成することができる.
ドライバの面では、まずclassを呼び出す必要があります.createはclassクラスを作成し、classクラスの下でdevice_を呼び出します.createはclassを作成しますデバイス、すなわちクラスの下にクラスを作成するデバイスです.(この方法は2.6以上のカーネルにのみ適用されます).
カーネルで定義されたstruct class構造体は、その名の通り、struct class構造体のタイプ変数がクラスに対応し、カーネルはclass_を提供します.create()関数は、sysfsの下に格納されたクラスを作成するために使用できます.このクラスを作成したら、device_を呼び出します.create()関数は、/devディレクトリの下で対応するデバイスノードを作成します.これにより、モジュールをロードすると、ユーザ空間のudevまたはmdevがdevice_に自動的に応答するcreate()関数は、/sysfsの下で対応するクラスを探してデバイスノードを作成します.
具体的な手順は次のとおりです.
1、classとdeviceの定義
static struct class *drv_class;
static struct device *drv_device;

2、classとdeviceの作成(エントリ関数)
drv_class = class_create(THIS_MODULE, "drv"); //   
drv_device = device_create(drv_class, NULL, MKDEV(major, 0), NULL, "xxx"); //       ,            

3.クラスとデバイスのアンインストール(出口関数)
device_unregister(drv_device);  //       
class_destroy(drv_class); //   

以下に、参照するドライバソースコードを示します.
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include  //class create

#define SECOND_MAJOR    232

static int second_major = SECOND_MAJOR;
module_param(second_major, int, S_IRUGO);

//      
static struct class* seconddrv_class;
static struct device* seconddrv_device;

struct second_dev
{
    struct cdev cdev;
    atomic_t counter;
    //       
    struct timer_list s_timer;
};

static struct second_dev* second_devp;
static void second_timer_handler(unsigned long arg)
{
    mod_timer(&second_devp->s_timer, jiffies + HZ);
    atomic_inc(&second_devp->counter);

    printk(KERN_INFO "current jiffies is %ld
"
, jiffies); } static int second_open(struct inode* inode, struct file* filp) { init_timer(&second_devp->s_timer); second_devp->s_timer.function = &second_timer_handler; second_devp->s_timer.expires = jiffies + HZ; add_timer(&second_devp->s_timer); atomic_set(&second_devp->counter, 0); return 0; } static int second_release(struct inode* inode, struct file* filp) { del_timer(&second_devp->s_timer); return 0; } static ssize_t second_read(struct file* filp, char __user* buf, size_t count, loff_t* ppos) { int counter; counter = atomic_read(&second_devp->counter); if(put_user(counter, (int*)buf)) return -EFAULT; else return sizeof(unsigned int); } static const struct file_operations second_fops = { .owner = THIS_MODULE, .open = second_open, .release = second_release, .read = second_read, }; static void second_setup_cdev(struct second_dev* dev, int index) { int err, devno = MKDEV(second_major, index); cdev_init(&dev->cdev, &second_fops); dev->cdev.owner = THIS_MODULE; err = cdev_add(&dev->cdev, devno, 1); if(err) printk(KERN_ERR "Failed to add second device
"
); } static int __init second_init(void) { int ret; dev_t devno = MKDEV(second_major, 0); if(second_major) ret = register_chrdev_region(devno, 1, "second"); else { ret = alloc_chrdev_region(&devno, 0, 1, "second"); second_major = MAJOR(devno); } if(ret < 0) return ret; second_devp = kzalloc(sizeof(*second_devp),GFP_KERNEL); if(!second_devp) { ret = -ENOMEM; goto fail_malloc; } second_setup_cdev (second_devp, 0); // seconddrv seconddrv_class = class_create(THIS_MODULE, "seconddrv"); // seconddrv second , seconddrv_device = device_create(seconddrv_class, NULL, MKDEV(second_major, 0), NULL, "second"); return 0; fail_malloc: unregister_chrdev_region(devno, 1); return ret; } module_init(second_init); static void __exit second_exit(void) { cdev_del(&second_devp->cdev); kfree(second_devp); unregister_chrdev_region(MKDEV(second_major, 0), 1); // device_unregister(seconddrv_device); // class_destroy(seconddrv_class); } module_exit(second_exit); MODULE_AUTHOR("were0415"); MODULE_LICENSE("GPL v2");