linux scull 代码write 方法

write, 象 read, 可以传送少于要求的数据, 根据返回值的下列规则:

 

  • 如果值等于 count, 要求的字节数已被传送.
    • 如果正值, 但是小于 count, 只有部分数据被传送. 程序最可能重试写入剩下的数 据.
    • 如果值为 0, 什么没有写. 这个结果不是一个错误, 没有理由返回一个错误码. 再 一次, 标准库重试写调用. 我们将在第 6 章查看这种情况的确切含义, 那里介绍了 阻塞.
  • 一个负值表示发生一个错误; 如同对于读, 有效的错误值是定义于

<linux/errno.h>中.

 

不幸的是, 仍然可能有发出错误消息的不当行为程序, 它在进行了部分传送时终止. 这是 因为一些程序员习惯看写调用要么完全失败要么完全成功, 这实际上是大部分时间的情况, 应当也被设备支持. scull 实现的这个限制可以修改, 但是我们不想使代码不必要地复杂.

 

write 的 scull 代码一次处理单个量子, 如 read 方法做的:

 

ssize_t scull_write(struct file *filp, const char   user *buf, size_t count, loff_t *f_pos)

{

struct scull_dev *dev = filp->private_data; struct scull_qset *dptr;

int quantum = dev->quantum, qset = dev->qset; int itemsize = quantum * qset;

int item, s_pos, q_pos, rest;

ssize_t retval = -ENOMEM; /* value used in "goto out" statements */ if (down_interruptible(&dev->sem))

return -ERESTARTSYS;

 

/* find listitem, qset index and offset in the quantum */ item = (long)*f_pos / itemsize;

rest = (long)*f_pos % itemsize; s_pos = rest / quantum;

q_pos = rest % quantum;

/* follow the list up to the right position */ dptr = scull_follow(dev, item);

if (dptr == NULL)

goto out; if (!dptr->data)

{

dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL); if (!dptr->data)

goto out;

memset(dptr->data, 0, qset * sizeof(char *));

}

if (!dptr->data[s_pos])

{

dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL); if (!dptr->data[s_pos])

goto out;

}

/* write only up to the end of this quantum */ if (count > quantum - q_pos)

count = quantum - q_pos;

if (copy_from_user(dptr->data[s_pos]+q_pos, buf, count))

{

retval = -EFAULT; goto out;

}

*f_pos += count; retval = count;

 

 

 

 

 

out:

 

 

}


/* update the size */ if (dev->size < *f_pos)

dev->size = *f_pos;

 

up(&dev->sem); return retval;

 

posted @ 2019-07-05 15:38  樊伟胜  阅读(324)  评论(0编辑  收藏  举报