zoukankan      html  css  js  c++  java
  • 字符设备驱动范例

    模拟一个虚拟寄存器设备驱动

    1.编写驱动

    #include <linux/module.h>
    #include <linux/fs.h>
    #include <linux/init.h>
    #include <linux/cdev.h>
    #include <asm/uaccess.h>


    int dev1_registers[5];
    int dev2_registers[5];

    struct cdev cdev;
    dev_t devno;

    /*文件打开函数*/
    int mem_open(struct inode *inode, struct file *filp)
    {

    /*获取次设备号*/
    int num = MINOR(inode->i_rdev);

    if (num==0)
    filp->private_data = dev1_registers;
    else if(num == 1)
    filp->private_data = dev2_registers;
    else
    return -ENODEV; //无效的次设备号

    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;
    int *register_addr = filp->private_data; /*获取设备的寄存器基地址*/

    /*判断读位置是否有效*/
    if (p >= 5*sizeof(int))
    return 0;
    if (count > 5*sizeof(int) - p)
    count = 5*sizeof(int) - p;

    /*读数据到用户空间*/
    if (copy_to_user(buf, register_addr+p, count))
    {
    ret = -EFAULT;
    }
    else
    {
    *ppos += count;
    ret = count;
    }

    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;
    int *register_addr = filp->private_data; /*获取设备的寄存器地址*/

    /*分析和获取有效的写长度*/
    if (p >= 5*sizeof(int))
    return 0;
    if (count > 5*sizeof(int) - p)
    count = 5*sizeof(int) - p;

    /*从用户空间写入数据*/
    if (copy_from_user(register_addr + p, buf, count))
    ret = -EFAULT;
    else
    {
    *ppos += count;
    ret = count;
    }

    return ret;
    }

    /* seek文件定位函数 */
    static loff_t mem_llseek(struct file *filp, loff_t offset, int whence)
    {
    loff_t newpos;

    switch(whence) {
    case SEEK_SET:
    newpos = offset;
    break;

    case SEEK_CUR:
    newpos = filp->f_pos + offset;
    break;

    case SEEK_END:
    newpos = 5*sizeof(int)-1 + offset;
    break;

    default:
    return -EINVAL;
    }
    if ((newpos<0) || (newpos>5*sizeof(int)))
    return -EINVAL;

    filp->f_pos = newpos;
    return newpos;

    }

    /*文件操作结构体*/
    static const struct file_operations mem_fops =
    {
    .llseek = mem_llseek,
    .read = mem_read,
    .write = mem_write,
    .open = mem_open,
    .release = mem_release,
    };

    /*设备驱动模块加载函数*/
    static int memdev_init(void)
    {
    /*初始化cdev结构*/
    cdev_init(&cdev, &mem_fops);

    /* 注册字符设备 */
    alloc_chrdev_region(&devno, 0, 2, "memdev");
    cdev_add(&cdev, devno, 2);
    }

    /*模块卸载函数*/
    static void memdev_exit(void)
    {
    cdev_del(&cdev); /*注销设备*/
    unregister_chrdev_region(devno, 2); /*释放设备号*/
    }

    MODULE_LICENSE("GPL");

    module_init(memdev_init);
    module_exit(memdev_exit);

    2.创建设备文件,首先查看开发板上文件系统中的设备编号

    cat /proc/devices 找到memdev 的设备编号,我这里是252

    mknod dev/memdev0 c 252 0

    3.编写write.c文件

    vim write.c
    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    int main()
    {
    int fd =0;//
    int src = 2013;
    fd=open("/dev/memdev0",O_RDWR);//以可读可写的方式打开文件,打开之
    后会返回一个fd,
    write(fd,&src,sizeof(int));向文件中写入数据,首先写入fd,然后写入
    数据,数据的大小。
    close(fd);
    }

    4.编写读取数据read.c文件

    vim read_mem.c
    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    int main()
    {
    int fd =0;
    int dst=0;
    fd = open("/dev/memdev0",O_RDWR);
    read (fd,&dst,sizeof(int));
    printf("dst is %d ",dst);
    return 0;
    }

    5.编写makefile

    这里就省略,很简单。 

    make

    arm-linux-gcc -static write.c -o write

    arm-linux-gcc -static read.c -o read

    6.将编译好的模块,以及write read 拷贝到nfs文件系统中

    安装内核模块 insmod memdev.ko

    ./write

    ./read

  • 相关阅读:
    洛谷P1129 [ZJOI2007] 矩阵游戏(二分图最大匹配)
    牛客NC51316 Going Home (二分图最大权匹配)
    洛谷P2055 [ZJOI2009]假期的宿舍(二分图最大匹配)
    Codeforces Round #702 (Div. 3) 全部七题
    Educational Codeforces Round 104 (Rated for Div. 2) A~D
    Leetcode 567. 字符串的排列(滑动窗口)
    基于macOS Catalina 10.15.7下GitHub Pages + Hexo 5.3.0 + 阿里云的博客部署
    关于两个数的LCM
    2021牛客寒假算法基础集训营1 补题 ABCEFIJ
    macOS上运行jupyter notebook程序:服务似乎挂掉了,但是会立刻重启 报错OMP: Error #15: Initializing libomp.dylib, but found libiomp5.dylib already initialize
  • 原文地址:https://www.cnblogs.com/defen/p/4730684.html
Copyright © 2011-2022 走看看