代码:编写一个简单的字符设备驱动(自动创建设备文件)

来源:互联网 发布:淘宝上怎么买qq号 编辑:程序博客网 时间:2024/05/19 16:22

说明:

(1)该篇在上篇的基础上实现了自动创建设备文件的功能;

(2)自动创建文件主要用到了class_create()、device_create()两个函数,声明在inclue/linux/device.h里;

(3)设备文件的创建和销毁放在模块加载和卸载函数中;

#include <linux/module.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/cdev.h>#include <linux/slab.h>#include <linux/uaccess.h>#include <linux/device.h>#define MAX_SIZE    0x1000#define MEM_CLEAR         0x1static struct class *class;static struct device *dev;struct virtdev_dev{    struct cdev cdev;    unsigned char mem[MAX_SIZE];};struct virtdev_dev *devp;dev_t devno;static int virtdev_open(struct inode *inode, struct file *filp){    filp->private_data = devp;    return 0;}static int virtdev_release(struct inode *inode, struct file *filp){    return 0;}static long virtdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){    struct virtdev_dev *dev = filp->private_data;        switch (cmd)    {    case MEM_CLEAR:        memset(dev->mem, 0, MAX_SIZE);        printk(KERN_INFO "virtdev is set to zero\n");        break;        default:        return -EINVAL;    }        return 0;}static ssize_t virtdev_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos){    unsigned long p = *ppos;    unsigned int count = size;    int ret = 0;    struct virtdev_dev *dev = filp->private_data;        if (p >= MAX_SIZE)        return -EINVAL;        if (count > MAX_SIZE - p)        count = MAX_SIZE - p;            if (copy_to_user(buf, dev->mem + p, count))        ret = -EINVAL;    else    {        *ppos += count;        ret = count;        printk(KERN_INFO "read %u byte(s) from %lu\n", count, p);    }        return ret;}static ssize_t virtdev_write(struct file *filp, const char __user *buf, size_t size,                    loff_t *ppos){    unsigned long p = *ppos;    unsigned int count = size;    int ret = 0;    struct virtdev_dev *dev = filp->private_data;        if (p >= MAX_SIZE)        return -EINVAL;    if (count > MAX_SIZE - p)        count = MAX_SIZE - p;            if (copy_from_user(dev->mem + p, buf, count))        ret = -EINVAL;    else    {        *ppos += count;        ret = count;        printk(KERN_INFO "write %u byte(s) from %lu\n", count, p);    }        return ret;}static loff_t virtdev_llseek(struct file *filp, loff_t offset, int orig){    loff_t ret = 0;        switch (orig)    {    case 0:        if (offset < 0)        {            ret = -EINVAL;            break;        }        if (offset > MAX_SIZE)        {            ret = -EINVAL;            break;        }        filp->f_pos = offset;        ret = filp->f_pos;        break;            case 1:        if ((filp->f_pos + offset) < 0 )        {            ret = -EINVAL;            break;        }                if ((filp->f_pos + offset) > MAX_SIZE)        {            ret = -EINVAL;            break;        }        filp->f_pos += offset;        ret = filp->f_pos;        break;            default:        ret = -EINVAL;        break;    }        return ret;}static const struct file_operations virtdev_fops ={    .owner  =  THIS_MODULE,    .llseek =  virtdev_llseek,    .read   =  virtdev_read,    .write  =  virtdev_write,    .unlocked_ioctl = virtdev_ioctl,    .open   =  virtdev_open,    .release = virtdev_release,};static char *chardev_devnode(struct device *dev, umode_t *mode){    if (mode)        *mode = 0666;    return NULL;}static int __init virtdev_init(void){    int ret;    int err;        ret = alloc_chrdev_region(&devno, 0, 1, "virtdev");    if (ret < 0)        return ret;            devp = kzalloc(sizeof(struct virtdev_dev), GFP_KERNEL);    if (!devp)    {        ret = -ENOMEM;        goto fail_malloc;    }        class = class_create(NULL, "virtdev");    if (IS_ERR(class))    {        ret = PTR_ERR(class);        printk(KERN_ERR "class create error %d\n", ret);        goto fail_malloc;    }        class->devnode = chardev_devnode;    dev = device_create(class, NULL, devno, NULL, "virtdev");    if (IS_ERR(class))    {        ret = PTR_ERR(dev);        printk(KERN_ERR "device create error %d\n", ret);        goto bad_device_create;    }            cdev_init(&devp->cdev, &virtdev_fops);    devp->cdev.owner = THIS_MODULE;    err = cdev_add(&devp->cdev, devno, 1);    if (err)        printk(KERN_NOTICE "Error %d adding virtdev", err);            return 0;        bad_device_create:    class_destroy(class);fail_malloc:    unregister_chrdev_region(devno, 1);    return ret;}static void __exit virtdev_exit(void){    device_destroy(class, devno);    class_destroy(class);    cdev_del(&devp->cdev);    kfree(devp);    unregister_chrdev_region(devno, 1);}module_init(virtdev_init);module_exit(virtdev_exit);MODULE_AUTHOR("lql");MODULE_LICENSE("GPL");

相关Makefile文件:

obj-m := test.oKDIR := /lib/modules/$(shell uname -r)/buildPWD  := $(shell pwd)all:make -C $(KDIR) M=$(PWD) modulesclean:rm -rf *.o *.ko *.mod.o *.mod.c *.symvers *.order

运行结果如下:

allen-lql dev # echo "hello everyone!" > virtdev allen-lql dev # cat virtdev hello everyone!

0 0
原创粉丝点击