zoukankan      html  css  js  c++  java
  • 小松之LINUX 驱动学习笔记(二)

    这两天一直在看字符驱动那块,后来从网上找啦几个例子,自己编译啦下,安装啥的都挺正常,就是用测试程序测试的时候总出问题,现在找到一个能测试的代码,自己先看看和原来的那个代码有啥不同,后面会继续更新,说下到底是啥问题导致驱动不能用。先附上能用代码的链接,这里先谢谢作者:

    http://blog.chinaunix.net/uid-22666248-id-3052861.html

    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/init.h>
    
    #include <linux/cdev.h>
    #include <linux/device.h>
    #include <linux/slab.h>//kmalloc
    #include <linux/vmalloc.h>//vmalloc()
    #include <linux/types.h>//ssize_t
    #include <linux/fs.h>//file_operaiotns
    #include <linux/uaccess.h>//copy_from_user
    
    #define MEM_MALLOC_SIZE 4096 ////缓冲区大小
    #define MEM_MAJOR    240 ////主设备号
    #define MEM_MINOR    0
    
    char *mem_spvm = NULL; ////缓冲区指针,指向内存区
    struct cdev *mem_cdev = NULL; //字符设备对象指针
    struct class *mem_class = NULL; //设备类指针
    
    static int __init mem_init(void);
    static void __exit mem_exit(void);
    static int mem_open(struct inode *inode,struct file *filp);
    static int mem_release(struct inode *inode, struct file *filp);
    static ssize_t mem_read(struct file *filp,char __user *buf,size_t count,loff_t *fpos);
    static ssize_t mem_write(struct file *filp, char __user *buf,size_t count ,loff_t *fops);
    
    static const struct file_operations mem_fops={
        .owner = THIS_MODULE,
        .open = mem_open,
        .release = mem_release,
        .read = mem_read,
        .write = mem_write,
    };
    
    static int __init mem_init(void)
    {
        int ret;
        //创建设备号 主次设备号
        int devno = MKDEV(MEM_MAJOR,MEM_MINOR);
        printk("mem_init initial...
    ");
    
        //开辟内核内存缓冲区
        mem_spvm = (char *)vmalloc(MEM_MALLOC_SIZE);
        if(mem_spvm == NULL)
        {
            printk("vmalloc mem_spvm error
    ");
            return -ENOMEM;//
        }
        
        //
        mem_cdev = cdev_alloc();
        if(mem_cdev == NULL)
        {
            printk("cdev_alloc error
    ");
            return -ENOMEM;
        }
        cdev_init(mem_cdev,&mem_fops);
        mem_cdev->owner = THIS_MODULE;
        ret = cdev_add(mem_cdev,devno,1);//将字符设备键入内核系统
        if(ret)
        {
            cdev_del(mem_cdev);
            mem_cdev = NULL;
            printk("cdev_add error
    ");
            return -1;
        }
    
        //
        mem_class = class_create(THIS_MODULE,"ywx_class_char");
        if(IS_ERR(mem_class))
        {
            printk("class_create error..
    ");
            return -1;
        }
        device_create(mem_class,NULL,MKDEV(MEM_MAJOR,MEM_MINOR),NULL,"ywx_device_char");
        
        printk("init finished..
    ");
        return 0;
    }
    
    static void __exit mem_exit(void)
    {
        printk("mem_exit starting..
    ");
        if(mem_cdev != NULL)
            cdev_del(mem_cdev);
        printk("cdev_del ok
    ");
    
        device_destroy(mem_class,MKDEV(MEM_MAJOR,MEM_MINOR));
        class_destroy(mem_class);
    
        if(mem_spvm != NULL)
            vfree(mem_spvm);
    
        printk("vfree ok
    ");
        printk("mem_exit finished..
    ");
    }
    
    static int mem_open(struct inode *inode,struct file *filp)
    {
        printk("open vmalloc space..
    ");
        try_module_get(THIS_MODULE);//模块引用计数器自加
        printk("open vamlloc space ok..
    ");
        return 0;
    }
    static int mem_release(struct inode *inode, struct file *filp)
    {
        printk("close vmalloc space..
    ");
        module_put(THIS_MODULE);//模块引用计数器自减
        return 0;
    }
    static ssize_t mem_read(struct file *filp,char __user *buf,size_t count,loff_t *fpos)
    {
        int ret = -1;
        char *tmp;
        printk("copy data to the user space
    ");
        tmp = mem_spvm;
        if(count > MEM_MALLOC_SIZE)
            count = MEM_MALLOC_SIZE;
        if(tmp != NULL)//将内核数据写入到用户空间
            ret = copy_to_user(buf,tmp,count);
        if(ret == 0)
        {
            printk("read copy data success
    ");
            return count;
        }
        else
        {
            printk("read copy data error
    ");
            return 0;
        }
    }
    static ssize_t mem_write(struct file *filp, char __user *buf,size_t count ,loff_t *fops)
    {
        int ret = -1;
        char *tmp;
        printk("read data from the user space.
    ");
        tmp = mem_spvm;
        if(count > MEM_MALLOC_SIZE)
            count = MEM_MALLOC_SIZE;
        if(tmp != NULL)
            ret = copy_from_user(tmp,buf,count);
        if(ret == 0)
        {
            printk("write copy data success.
    ");
            return count;
        }
        else
        {
            printk("write copy data error.
    ");
            return 0;    
        }
    }
    
    MODULE_LICENSE("GPL");
    module_init(mem_init);
    module_exit(mem_exit);
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <string.h>//memset()
    
    int main(int argc, char *argv[])
    {
        int fd,cnt;
        char buf[256];
        int i;
        printf("char device testing..
    ");
        fd = open("/dev/ywx_device_char",O_RDWR);
        if(fd == 0)
        {
            printf("open failed.
    ");
            return 1;
        }
        
        printf("input the data for kernel:");
        scanf("%s",buf);
        cnt = write(fd,buf,256);
        if(cnt == 0)
            printf("write error
    ");
        
        printf("clear buf,and will read from kernel...
    ");
        for(i=0;i<256;i++)
            buf[i] = 32;//32 =" "
    
        cnt = read(fd,buf,256);
        if(cnt > 0)
            printf("read data from kernel is:%s
    ",buf);
        else
            printf("read data error
    ");
        close(fd);
        printf("close app..
    ");
        return 0;
    }

    运行的时候用root用户运行,可以看到/dev目录下有设备节点,然后运行test文件,可以看到能运行。

    make;sudo insmod xxx.ko; sudo ./app

  • 相关阅读:
    后缀数组
    网络流 HOJ1087
    备用
    css-具有缩略图的材料列表
    正则匹配log行
    vue-cli的webpack打包,icon无法正确加载
    导出CSV,导出excel数字过长显示科学计数法解决方案
    js导出CSV
    git常见操作指令
    javascript原型的意义
  • 原文地址:https://www.cnblogs.com/cainiaoaixuexi/p/3688424.html
Copyright © 2011-2022 走看看