字符设备驱动第四课----自动生成设备

来源:互联网 发布:上传淘宝图片尺寸 编辑:程序博客网 时间:2024/04/29 13:12

【概述】

前面的时候我们要在应用程序中使用我们自己写的内核模块要做以下步骤:

1.insmod
2.mknod /dev/demo1 c 250 0
3.在运用程序中调用open(“/dev/demo1”,O_RDWR)打开我们自己创建的设备

现在问题来了,难道每次使用设备都要让用户(写运用程序的人)自己去创建设备吗?这显然不好,所以本节课就要解决“在驱动中自动创建设备”这个问题。

【涉及到的内核接口函数】

1.创建一个类

其实质是个目录,将同一类设备(共用同一个驱动程序的设备)归纳到其目录下,目录下是具体的设备。
/** 功能: 创建一个目录* 输入参数: owner:THIS_MODULE*          name:目录名* 返回值: 成功:返回对象指针 失败:错误码*/struct class *class_create(owner, name)

2.创建一个设备:

跟手动敲mknod命令效果一样
<driver/base/core.h>/** 功能:创建一个设备* 输入参数:struct class *:所属对象,上一步创建的对象*         struct device *parent:父设备*         dev_t:将要创建的设备*         void *drvdata:驱动传入的一些数据*         const char *fmt:路径* 返回值:成功:返回所创建的设备 失败:返回错误码*/struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)

3.销毁一个设备:

跟手动敲rmnod命令效果一样
<drivers/base/core.c>/** 功能: 销毁指定设备* 输入参数:struct class:所属类的指针*         dev_t:设备号* 返回值: none*/void device_destroy(struct class *class, dev_t devt)

4.销毁一个类:

<drivers/base/driver.h>/** 功能: 销毁一个类* 输入参数:struct class *:类指针* 返回值:none*/void class_destroy(struct class *cls);

【工程实例】

#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/cdev.h>#include <linux/fs.h>#include <linux/errno.h>#include <asm/current.h>#include <linux/sched.h>#include <linux/device.h>static struct class *cls = NULL;static int major = 0;static int minor = 0;const  int count = 6;#define DEVNAME "demo"static struct cdev *demop = NULL;//打开设备static int demo_open(struct inode *inode, struct file *filp){    //get command and pid    printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n",        current->comm, current->pid, __FILE__, __func__, __LINE__);    //get major and minor from inode    printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n",        imajor(inode), iminor(inode), __FILE__, __func__, __LINE__);    return 0;}//关闭设备static int demo_release(struct inode *inode, struct file *filp){    //get command and pid    printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n",        current->comm, current->pid, __FILE__, __func__, __LINE__);    //get major and minor from inode    printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n",        imajor(inode), iminor(inode), __FILE__, __func__, __LINE__);    return 0;}//读设备//ssize_t read(int fd, void *buf, size_t count)static ssize_t demo_read(struct file *filp, char __user *buf, size_t size, loff_t *offset){    struct inode *inode = filp->f_path.dentry->d_inode;    //get command and pid    printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n",        current->comm, current->pid, __FILE__, __func__, __LINE__);    //get major and minor from inode    printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n",        imajor(inode), iminor(inode), __FILE__, __func__, __LINE__);    return 0;}//写设备static ssize_t demo_write(struct file *filp, const char __user *buf, size_t size, loff_t *offset){    struct inode *inode = filp->f_path.dentry->d_inode;    //get command and pid    printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n",        current->comm, current->pid, __FILE__, __func__, __LINE__);    //get major and minor from inode    printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n",        imajor(inode), iminor(inode), __FILE__, __func__, __LINE__);    return 0;}static struct file_operations fops = {    .owner  = THIS_MODULE,    .open   = demo_open,    .release= demo_release,    .read   = demo_read,    .write  = demo_write,};static int __init demo_init(void){    dev_t devnum;    int ret, i;    struct device *devp = NULL;    //get command and pid    printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n",        current->comm, current->pid, __FILE__, __func__, __LINE__);    //1. alloc cdev obj    demop = cdev_alloc();    if(NULL == demop){        return -ENOMEM;    }    //2. init cdev obj    cdev_init(demop, &fops);    ret = alloc_chrdev_region(&devnum, minor, count, DEVNAME);    if(ret){        goto ERR_STEP;    }    major = MAJOR(devnum);    //3. register cdev obj    ret = cdev_add(demop, devnum, count);    if(ret){        goto ERR_STEP1;    }    cls = class_create(THIS_MODULE, DEVNAME);    if(IS_ERR(cls)){        ret = PTR_ERR(cls);        goto ERR_STEP1;    }    for(i = minor; i < (count+minor); i++){        devp = device_create(cls, NULL, MKDEV(major, i), NULL, "%s%d", DEVNAME, i);        if(IS_ERR(devp)){            ret = PTR_ERR(devp);            goto ERR_STEP2;        }    }    //get command and pid    printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - ok.\n",        current->comm, current->pid, __FILE__, __func__, __LINE__);    return 0;ERR_STEP2:    for(--i; i >= minor; i--){        device_destroy(cls, MKDEV(major, i));    }    class_destroy(cls);ERR_STEP1:    unregister_chrdev_region(devnum, count);ERR_STEP:    cdev_del(demop);    //get command and pid    printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - fail.\n",        current->comm, current->pid, __FILE__, __func__, __LINE__);    return ret;}static void __exit demo_exit(void){    int i;    //get command and pid    printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - leave.\n",        current->comm, current->pid, __FILE__, __func__, __LINE__);    for(i=minor; i < (count+minor); i++){        device_destroy(cls, MKDEV(major, i));    }    class_destroy(cls);    unregister_chrdev_region(MKDEV(major, minor), count);    cdev_del(demop);}module_init(demo_init);module_exit(demo_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Farsight");MODULE_DESCRIPTION("Demo for kernel module");
0 0
原创粉丝点击