Linux内核驱动之read和write

搜索公众号:itxxgh  (IT学习干货),全公益,免费,定期,提供,《IT学习教程》。不会骚扰大家,只需轻点关注,也会传播《中华传统文化》传播正能量,扫码关注



读和写方法都进行类似的任务, 可以同时介绍它们:

ssize_t read(struct file *filp, char __user *buff, size_t count, loff_t *offp);
ssize_t write(struct file *filp, const char __user *buff, size_t count, loff_t *offp);

对于 2 个方法, filp 是文件指针, count 是请求的传输数据大小. buff 参数指向持有被写入数据的缓存, 或者放入新数据的空缓存. 最后, offp 是一个指针指向一个”long offset type”对象, 它指出用户正在存取的文件位置. 返回值是一个”signed size type”;

 

read 和 write 方法的 buff 参数是用户空间指针. 因此, 它不能被内核代码直接解引用. 为安全起见这个存取必须使用特殊的, 内核提供的函数. 我们介绍几个这样的函数(定义于 ),

unsigned long copy_to_user(void __user *to,const void *from,unsigned long count);

unsigned long copy_from_user(void *to,const void __user *from,unsigned long count);

这 2 个函数的角色不限于拷贝数据到和从用户空间: 它们还检查用户空间指针是否有效. 如果指针无效, 不进行拷贝; 如果在拷贝中遇到一个无效地址, 另一方面, 只拷贝部分数据. 在 2 种情况下, 返回值是还要拷贝的数据量. scull 代码查看这个错误返回, 并且如果它不是 0 就返回 -EFAULT 给用户.

至于实际的设备方法, read方法的任务是从设备拷贝数据到用户空间(使用 copy_to_user),而 write 方法必须从用户空间拷贝数据到设备(使用 copy_from_user).

read 和 write 方法都在发生错误时返回一个负值. 相反, 大于或等于 0 的返回值告知调用程序有多少字节已经成功传送. 如果一些数据成功传送接着发生错误, 返回值必须是成功传送的字节数,

点击(此处)折叠或打开

  1. ssize_t mem_read(struct file*filp, char __user*buf, size_t count, loff_t*f_pos)
  2. {
  3.     struct mem_dev *dev = filp->private_data;// 获得私有数据指针
  4.     int ret = 0;
  5.     
  6.     if(*f_pos> dev->size)// 判断文件是否已读完
  7.         goto out;

  8.     if(*f_pos+ count> dev->size)// 如果读的数据过大
  9.         count = dev->size- *f_pos;

  10.     if(copy_to_user(buf,(void*)(dev->data+ *f_pos),count))    // 返回数据至用户空间
  11.     {
  12.         ret = -EFAULT;
  13.         goto out;
  14.     }

  15.     *f_pos += count;    
  16.     ret = count;
  17. out:
  18.     return ret;
  19. }

  20. ssize_t mem_write(struct file *filp, const char __user*buf, size_t count, loff_t*f_pos)
  21. {
  22.     struct mem_dev *dev = filp->private_data;// 获得私有数据指针
  23.     int ret = 0;
  24.     
  25.     if(*f_pos> MEMDEV_SIZE)// 判断文件是否已到结尾
  26.         goto out;

  27.     if(*f_pos+ count > MEMDEV_SIZE)// 如果读的数据过大
  28.         count = MEMDEV_SIZE - *f_pos;

  29.     if(copy_from_user(dev->data+ *f_pos,buf,count))    
  30.     {
  31.         ret = -EFAULT;
  32.         goto out;
  33.     }

  34.     *f_pos += count;    
  35.     ret = count;

  36.     if (dev->size< *f_pos)    
  37.         dev->size= *f_pos;
  38.     
  39. out:
  40.     return ret;
  41. }


  42. struct file_operations my_fops =
  43. {
  44.     .owner = THIS_MODULE,
  45.     .open = mem_open,
  46.     .release = mem_release,
  47.     .read = mem_read,
  48.     .write = mem_write,
  49. };




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值