驱动学习笔记2 字符设备驱动硬件操作接口read

字符设备驱动操作接口之read


a)回顾read系统调用函数


    函数原型:
    ssize_t  read(int fd, void *buf, size_t count)
    功能:从硬件设备中读取数据
    参数:
    fd:设备文件描述符,对应就是文件,本质最终对应硬件外设
    buf:用于保存数据的用户缓冲区首地址
    count:希望读取的字节数
    返回值:返回实际读取的字节数
参考代码:
    //读取字符串
    char str[1024] = {0};
    read(fd, str, 1024); //从硬件读取字符串数据保存到str数组中
    printf("%s\n", str); //打印读取的字符串数据
    //读取整形数
    int status;
    read(fd, &status, sizeof(status)); //从硬件读取数据保存到status变量中
    printf("%d\n", status);
    //读取数据
    int arr[2] = {0};
    read(fd, arr, 8); //从硬件设备读取8字节数据放到arr数组中
    printf("%d %d\n", arr[0], arr[1]);
    //读取结构体数据
    struct A {
         int a;
         int b;
    };
    struct A aa;
    read(fd, &aa, sizeof(aa)); //从硬件设备中读取一个结构体数据保存到aa中
    printf("%d %d\n", aa.a, aa.b);

b)底层驱动的read接口


    struct file_operations {
        ssize_t (*read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
    };
    功能:负责从硬件外设中读取数据,然后将读取到的数据拷贝给应用程序,拷贝到用户缓冲区中(pstr,status,arr,aa)
        起到了一个桥梁的作用,连接应用和硬件
        硬件数据->read->应用用户缓冲区
    参数:
    file:文件指针,file和应用read的第一个参数fd是亲戚关系,通过fd能够找到file
    buf:保存用户缓冲区的首地址(例如:buf=&status),同样底层驱动不能直接访问,太危险(*(int *)buf)
        必须利用内核提供的内存拷贝函数:copy_to_user,将内核缓冲区中的数据拷贝到用户缓冲区中
        int  copy_to_user(void __user *to, void *from, int n)
        功能:将内核缓冲区的数据拷贝到用户缓冲区中,帮你做地址的安全性检查
        参数:
        to:用户缓冲区的首地址
        from:内核缓冲区的首地址
        n:要拷贝的字节数
        count:等于应用程序read的第三个参数(例如:count=sizeof(status)),保存希望读取的字节数
        ppos:记录着上一次的读写位置,用于多次读取
编程步骤:
        1.先获取到上一次的读写位置
        loff_t  pos = *ppos;
        2.假如这次又读取了100字节,read接口返回之前记得更新读位置
        *ppos = pos + 100;
        返回值:返回实际读取的字节数,失败返回-1
    
    调用关系:应用read->C库read->触发软中断->内核的sys_read->底层驱动read接口
案例:编写LED字符设备驱动,实现:获取灯的开关状态
实施步骤:
上位机执行:
cp 2.0/ 4.0 -fr
vim led_test.c
vim led_drv.c

增加从硬件读取数据接口


vim Makefile
make
arm-cortex_a9-linux-gnueabi-gcc -o led_test led_test.c
cp led_test  led_drv.ko  /opt/rootfs/home/drivers/
下位机测试
cd /home/drivers
insmod led_drv.ko
cat /proc/device  查看申请的主设备号
mknod /dev/myled  c   244 0
./led_test on  //观察打印的灯的状态
./led_test off   

 

作业:编写LED驱动,利用read实现能够获取某个灯的开关状态

copyfrom再copyto

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值