zoukankan      html  css  js  c++  java
  • 字符设备模板1

    源代码:

    /****************************************************************************** 
    *Name: memdev.c 
    *Desc: 字符设备驱动程序的框架结构,该字符设备并不是一个真实的物理设备, 
    * 而是使用内存来模拟一个字符设备 
    *Parameter:  
    *Return: 
    *Author: derek 
    *Date: 2013-6-4 
    ********************************************************************************/  
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/types.h>
    #include <linux/spinlock.h>
    #include <linux/blkdev.h>
    #include <linux/module.h>  
    #include <linux/fs.h>  
    #include <linux/errno.h>  
    #include <linux/mm.h>  
    #include <linux/cdev.h>  
      
    #define MEMDEV_MAJOR        260 /*预设的mem的主设备号*/  
    #define MEMDEV_NR_DEVS      2 /*设备数*/  
    #define MEMDEV_SIZE         4096  
    #define CHAR_DEV_NAME       "memdev"
      
    /*mem设备描述结构体*/  
    struct mem_dev   
    {   
      char *data;   
      unsigned long size;   
    };  
      
    static int mem_major = MEMDEV_MAJOR;  
      
    module_param(mem_major, int, S_IRUGO);  
      
    struct mem_dev *mem_devp; /*设备结构体指针*/  
      
    struct cdev cdev;   
      
    /*文件打开函数*/  
    int mem_open(struct inode *inode, struct file *filp)  
    {  
        struct mem_dev *dev;  
          
        /*获取次设备号*/  
        int num = MINOR(inode->i_rdev);  
    
        if (num >= MEMDEV_NR_DEVS)   
                return -ENODEV;  
        dev = &mem_devp[num];  
          
        /*将设备描述结构指针赋值给文件私有数据指针*/  
        filp->private_data = dev;  
          
        return 0;   
    }  
      
    /*文件释放函数*/  
    int mem_release(struct inode *inode, struct file *filp)  
    {  
        return 0;  
    }  
      
    /*读函数*/  
    static ssize_t mem_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 mem_dev *dev = filp->private_data; /*获得设备结构体指针*/  
    
        /*判断读位置是否有效*/  
        if (p >= MEMDEV_SIZE)  
            return 0;  
        if (count > MEMDEV_SIZE - p)  
            count = MEMDEV_SIZE - p;  
    
        /*读数据到用户空间*/  
        if (copy_to_user(buf, (void*)(dev->data + p), count))  
        {  
            ret = - EFAULT;  
        }  
        else  
        {  
            *ppos += count;  
            ret = count;  
            printk(KERN_INFO "read %d bytes(s) from %d
    ", count, p);  
        }  
    
        return ret;  
    }  
      
    /*写函数*/  
    static ssize_t mem_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 mem_dev *dev = filp->private_data; /*获得设备结构体指针*/  
    
        /*分析和获取有效的写长度*/  
        if (p >= MEMDEV_SIZE)  
            return 0;  
        if (count > MEMDEV_SIZE - p)  
            count = MEMDEV_SIZE - p;  
    
        /*从用户空间写入数据*/  
        if (copy_from_user(dev->data + p, buf, count))  
            ret = - EFAULT;  
        else  
        {  
            *ppos += count;  
            ret = count;  
            printk(KERN_INFO "written %d bytes(s) from %d
    ", count, p);  
        }  
    
        return ret;  
    }  
      
    /* seek文件定位函数 */  
    static loff_t mem_llseek(struct file *filp, loff_t offset, int whence)  
    {   
        loff_t newpos;  
      
        switch(whence) {  
          case 0: /* SEEK_SET */  
            newpos = offset;  
            break;  
      
          case 1: /* SEEK_CUR */  
            newpos = filp->f_pos + offset;  
            break;  
      
          case 2: /* SEEK_END */  
            newpos = MEMDEV_SIZE -1 + offset;  
            break;  
      
          default: /* can't happen */  
            return -EINVAL;  
        }  
        if ((newpos<0) || (newpos>MEMDEV_SIZE))  
         return -EINVAL;  
           
        filp->f_pos = newpos;  
        return newpos;  
    }  
      
    /*文件操作结构体*/  
    static const struct file_operations mem_fops =  
    {  
        .owner = THIS_MODULE,  
        .llseek = mem_llseek,  
        .read = mem_read,  
        .write = mem_write,  
        .open = mem_open,  
        .release = mem_release,  
    };  
    
    struct class *pclass;  
    
    /*设备驱动模块加载函数*/  
    static int memdev_init(void)  
    {  
        int result;  
        int i;  
    
        dev_t devno = MKDEV(mem_major, 0);  
    
        if (mem_major)  { /* 静态申请设备号*/  
            result = register_chrdev_region(devno, 2, CHAR_DEV_NAME);  
        } else {/* 动态分配设备号 */  
            result = alloc_chrdev_region(&devno, 0, 2, CHAR_DEV_NAME);  
            mem_major = MAJOR(devno);  
        }   
    
        if (result < 0)  
            return result;  
    
        /*初始化cdev结构*/  
        cdev_init(&cdev, &mem_fops);  
        cdev.owner = THIS_MODULE;  
        cdev.ops = &mem_fops;  
    
        /* 注册字符设备 */  
        cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS);  
    
        /* 为设备描述结构分配内存*/  
        mem_devp = kmalloc(MEMDEV_NR_DEVS * sizeof(struct mem_dev), GFP_KERNEL);  
        if (!mem_devp) /*申请失败*/  
        {  
            result = - ENOMEM;  
            goto fail_malloc;  
        }  
        memset(mem_devp, 0, sizeof(struct mem_dev));  
    
        /*为设备分配内存*/  
        for (i=0; i < MEMDEV_NR_DEVS; i++)   
        {  
            mem_devp[i].size = MEMDEV_SIZE;  
            mem_devp[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);  
            memset(mem_devp[i].data, 0, MEMDEV_SIZE);  
        }  
    
        pclass = class_create(THIS_MODULE, CHAR_DEV_NAME);  
        if (IS_ERR(pclass))  
        {  
            printk("class_create failed!/n");  
            kfree(mem_devp);
            goto fail_malloc;  
        }  
    
        device_create(pclass, NULL, devno, NULL, CHAR_DEV_NAME);  
        return 0;  
    
    fail_malloc:   
        unregister_chrdev_region(devno, 1);  
        return result;  
    }  
      
    /*模块卸载函数*/  
    static void memdev_exit(void)  
    {  
        device_destroy(pclass, MKDEV(mem_major, 0));  
        class_destroy(pclass);
        cdev_del(&cdev); /*注销设备*/  
        kfree(mem_devp); /*释放设备结构体内存*/  
        unregister_chrdev_region(MKDEV(mem_major, 0), 2); /*释放设备号*/  
    }  
      
    MODULE_AUTHOR("derek yi");  
    MODULE_LICENSE("GPL");  
      
    module_init(memdev_init);  
    module_exit(memdev_exit);  

    makefile:

    ifneq ($(KERNELRELEASE),)
    
    obj-m:=memdev.o
    
    else
    
    KERNELDIR:=/lib/modules/$(shell uname -r)/build
    PWD:=$(shell pwd)
    
    default:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
    
    clean:
        rm -rf *.o *.mod.c *.mod.o *.ko
    
    endif

    测试代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <unistd.h>
    #include <linux/fcntl.h>
    
    int main()
    {
        int fd;
        char buf[]="this is a example for character devices driver by derek!";
        char buf_read[4096]; //memdev设备的内容读入到该buf中
    
        if((fd = open("/dev/memdev",O_RDWR))==-1) //打开memdev设备
            printf("open memdev WRONG!
    ");
        else
            printf("open memdev SUCCESS!
    ");
    
        printf("write: %s
    ", buf); 
    
        write(fd, buf, sizeof(buf)); //把buf中的内容写入memdev设备 
        lseek(fd, 0, SEEK_SET); //把文件指针重新定位到文件开始的位置 
        read(fd, buf_read, sizeof(buf)); //把memdev设备中的内容读入到buf_read中
    
        printf("read: %s
    ",buf_read);
        close(fd);
    
        return 0;
    }
  • 相关阅读:
    STM32.ADC
    电源方案集
    什么叫二级域名
    android驱动学习---led实验
    Get,Post和Head具体解释
    Android 编码规范
    VC:当前不会命中断点,还没有为该文档载入不论什么符号
    经常使用的结构体
    【Facebook的UI开发框架React入门之九】button简单介绍(iOS平台)-goodmao
    记录遇到的ios下的bugs[废弃]
  • 原文地址:https://www.cnblogs.com/soul-stone/p/6384592.html
Copyright © 2011-2022 走看看