zoukankan      html  css  js  c++  java
  • 一个简单的字符设备驱动

    .h文件

    #ifndef _DEMO_H_
    #define _DEMO_H_
    #include <linux/ioctl.h>
    /*Macros to help debuging*/
    #undef PDEBUG
    #ifdef DEMO_DEBUG
        #ifdef __KERNEL__
            #define PDEBUG(fmt, args...) printk(KERN_DEBUG "DEMO:" fmt,## args)
        #else
            #define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
        #endif
    #else
    #define PDEBUG(fmt, args...)
    #endif
    
    #define DEMO_MAJOR 224
    #define DEMO_MINOR 0
    #define COMMAND1 1
    #define COMMAND2 2
    
    struct demo_dev {
                struct cdev cdev;
    };
    
    ssize_t demo_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
    ssize_t demo_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);
    loff_t demo_llseek(struct file *filp, loff_t off, int whence);
    static long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
    
    #endif

    .c文件

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/fs.h>
    #include <linux/errno.h>
    #include <linux/types.h>
    #include <linux/fcntl.h>
    #include <linux/cdev.h>
    #include <linux/version.h>
    #include <linux/vmalloc.h>
    #include <linux/ctype.h>
    #include <linux/pagemap.h>
    #include <linux/slab.h>
    #include <linux/device.h>
    #include "demo.h"
    
    MODULE_AUTHOR("Gaowei");
    MODULE_LICENSE("Dual BSD/GPL");
    
    struct demo_dev *demo_devices;
    
    static unsigned char demo_inc = 0;//全局变量,每次只能打开一个设备
    
    static u8 demo_buffer[256];
    static struct class *demo_class;
    int demo_open(struct inode *inode, struct file *filp)
    {
            struct demo_dev *dev;
    
            if (demo_inc > 0) return -ERESTARTSYS;
            demo_inc++;
            dev = container_of(inode->i_cdev, struct demo_dev, cdev);
            filp->private_data = dev;
    
            return 0;
    }
    
    int demo_release(struct inode *inode, struct file *filp)
    {
            demo_inc--;
            return 0;
    }
    
    ssize_t demo_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
    {
            int result;
            loff_t pos = *f_pos; //pos: offset
    
            if (pos >= 256) {
                    result = 0;
                    goto out;
            }
            if (count > (256 - pos))
                    count = 256 - pos;
            pos += count;
    
            if (copy_to_user(buf, demo_buffer+*f_pos, count)) {
                    count = -EFAULT;
                    goto out;
            }
    
            *f_pos = pos;
    out:
            return count;
    }
    
    ssize_t  demo_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
    {
            ssize_t retval = -ENOMEM;
            loff_t pos = *f_pos;
    
            if (pos > 256)
                    goto out;
            if (count > (256 - pos))
                    count = 256 - pos;
            pos += count;
            if (copy_from_user(demo_buffer+*f_pos, buf, count)) {
                    retval = -EFAULT;
                    goto out;
            }
    
            *f_pos = pos;
            retval = count;
    out:
            return retval;
    }
    
    static long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    {
            if (cmd == COMMAND1) {
                    printk("ioctl command 1 successfully
    ");
                    return 0;
            }
            if (cmd == COMMAND2) {
                    printk("ioctl command 2 successfully
    ");
                    return 0;
            }
            printk("ioctl error
    ");
            return -EFAULT;
    }
    
    loff_t demo_llseek(struct file *filp, loff_t off, int whence)
    {
            loff_t pos;
    
            pos = filp->f_pos;
            switch (whence) {
                    case 0:
                            pos = off;
                            break;
                    case 1:
                            pos += off;
                            break;
                    case 2:
                    default:
                            return -EINVAL;
            }
    
            if ((pos > 256) || (pos < 0))
                    return -EINVAL;
    
            return filp->f_pos = pos;
    }
    
    struct file_operations demo_fops = {
            .owner = THIS_MODULE,
            .llseek = demo_llseek,
            .read = demo_read,
            .write = demo_write,
            .unlocked_ioctl = demo_ioctl,
            .open = demo_open,
            .release = demo_release,
    };
    
    void demo_cleanup_module(void)
    {
            dev_t devno = MKDEV(DEMO_MAJOR, DEMO_MINOR);
    
            if (demo_devices) {
                    cdev_del(&demo_devices->cdev);
                    kfree(demo_devices);
            }
            unregister_chrdev_region(devno, 1);
    }
    
    /*Init module流程:
    1)注册设备号MKDEV;
    2)注册设备驱动程序,即初始化cdev结构(嵌入到demo_devices结构中)*/
    int demo_init_module(void)
    {
            int result;
            dev_t dev = 0;
    
            dev = MKDEV(DEMO_MAJOR, DEMO_MINOR);
            result = register_chrdev_region(dev, 1, "DEMO");
            if (result < 0) {
                    printk(KERN_WARNING "DEMO: can't get major %d
    ", DEMO_MAJOR);
                    return result;
            }
            demo_devices = kmalloc(sizeof(struct demo_dev), GFP_KERNEL);
            if (!demo_devices) {
                    result = -ENOMEM;
                    goto fail;
            }
            memset(demo_devices, 0, sizeof(struct demo_dev));
            cdev_init(&demo_devices->cdev, &demo_fops);
            demo_devices->cdev.owner = THIS_MODULE;
            result = cdev_add(&demo_devices->cdev, dev, 1);
            if (result) {
                    printk(KERN_NOTICE "error %d adding demo
    ", result);
                    goto fail;
            }
            demo_class = class_create(THIS_MODULE, "DEMO");
            device_create(demo_class, NULL, MKDEV(DEMO_MAJOR, DEMO_MINOR), NULL, "DEMO"); // create a device
            return 0;
    fail:
            demo_cleanup_module();
            return result;
    }
    
    module_init(demo_init_module);
    module_exit(demo_cleanup_module);

    Makefile文件

    obj-m:=demo.o
    KDIR := /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)
    
    all:
            $(MAKE) -C $(KDIR) M=$(PWD) modules
    
    clean:
            $(MAKE) -C $(KDIR) M=$(PWD) clean
  • 相关阅读:
    厦门主要IT企业名单(至20071205)
    空,无
    扩展TextBox控件 荣
    我写的C++控件基类 荣
    扩展DataGrid 荣
    对重构的理解 荣
    C#中的委托与事件 荣
    CommunityServer中的代码页面分离 荣
    Oracle创建表空间,导出数据库,导入数据库 荣
    C#中的修饰符 荣
  • 原文地址:https://www.cnblogs.com/chaozhu/p/6245083.html
Copyright © 2011-2022 走看看