Linux内核驱动之read和write

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

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. };

你可能感兴趣的:(Linux内核驱动之read和write)