⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch03s07.html

📁 介绍Linux内核驱动编程的一本书 最主要的是有源代码,都是可用的 学习操作系统很好
💻 HTML
📖 第 1 页 / 共 2 页
字号:
        up(&amp;dev-&gt;sem);        return retval;}</pre></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="ThewriteMethod.sect"></a>3.7.2.&#160;write 方法</h3></div></div></div><p>write, 象 read, 可以传送少于要求的数据, 根据返回值的下列规则:</p><div class="itemizedlist"><ul type="disc"><li><p>如果值等于 count, 要求的字节数已被传送.</p></li><li><p>如果正值, 但是小于 count, 只有部分数据被传送. 程序最可能重试写入剩下的数据.</p></li><li><p>如果值为 0, 什么没有写. 这个结果不是一个错误, 没有理由返回一个错误码. 再一次, 标准库重试写调用. 我们将在第 6 章查看这种情况的确切含义, 那里介绍了阻塞.</p></li><li><p>一个负值表示发生一个错误; 如同对于读, 有效的错误值是定义于 &lt;linux/errno.h&gt;中.</p></li></ul></div><p>不幸的是, 仍然可能有发出错误消息的不当行为程序, 它在进行了部分传送时终止. 这是因为一些程序员习惯看写调用要么完全失败要么完全成功, 这实际上是大部分时间的情况, 应当也被设备支持. scull 实现的这个限制可以修改, 但是我们不想使代码不必要地复杂.</p><p>write 的 scull 代码一次处理单个量子, 如 read 方法做的:</p><pre class="programlisting">ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){        struct scull_dev *dev = filp-&gt;private_data;        struct scull_qset *dptr;        int quantum = dev-&gt;quantum, qset = dev-&gt;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(&amp;dev-&gt;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-&gt;data)        {                dptr-&gt;data = kmalloc(qset * sizeof(char *), GFP_KERNEL);                if (!dptr-&gt;data)                        goto out;                memset(dptr-&gt;data, 0, qset * sizeof(char *));        }        if (!dptr-&gt;data[s_pos])        {                dptr-&gt;data[s_pos] = kmalloc(quantum, GFP_KERNEL);                if (!dptr-&gt;data[s_pos])                        goto out;        }        /* write only up to the end of this quantum */        if (count &gt; quantum - q_pos)                count = quantum - q_pos;        if (copy_from_user(dptr-&gt;data[s_pos]+q_pos, buf, count))        {                retval = -EFAULT;                goto out;        }        *f_pos += count;        retval = count;        /* update the size */        if (dev-&gt;size &lt; *f_pos)                dev-&gt;size = *f_pos;out:        up(&amp;dev-&gt;sem);        return retval;}</pre></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="readvandwritev.sect"></a>3.7.3.&#160;readv 和 writev</h3></div></div></div><p>Unix 系统已经长时间支持名为 readv 和 writev 的 2 个系统调用. 这些 read 和 write 的"矢量"版本使用一个结构数组, 每个包含一个缓存的指针和一个长度值. 一个 readv 调用被期望来轮流读取指示的数量到每个缓存. 相反, writev 要收集每个缓存的内容到一起并且作为单个写操作送出它们.</p><p>如果你的驱动不提供方法来处理矢量操作, readv 和 writev 由多次调用你的 read 和 write 方法来实现. 在许多情况, 但是, 直接实现 readv 和 writev 能获得更大的效率.</p><p>矢量操作的原型是:</p><pre class="programlisting">ssize_t (*readv) (struct file *filp, const struct iovec *iov, unsigned long count, loff_t *ppos);ssize_t (*writev) (struct file *filp, const struct iovec *iov, unsigned long count, loff_t *ppos);</pre><p>这里, filp 和 ppos 参数与 read 和 write 的相同. iovec 结构, 定义于 &lt;linux/uio.h&gt;, 如同:</p><pre class="programlisting">struct iovec{    void __user *iov_base; __kernel_size_t iov_len;};</pre><p>每个 iovec 描述了一块要传送的数据; 它开始于 iov_base (在用户空间)并且有 iov_len 字节长. count 参数告诉有多少 iovec 结构. 这些结构由应用程序创建, 但是内核在调用驱动之前拷贝它们到内核空间.</p><p>矢量操作的最简单实现是一个直接的循环, 只是传递出去每个 iovec 的地址和长度给驱动的 read 和 write 函数. 然而, 有效的和正确的行为常常需要驱动更聪明. 例如, 一个磁带驱动上的 writev 应当将全部 iovec 结构中的内容作为磁带上的单个记录.</p><p>很多驱动, 但是, 没有从自己实现这些方法中获益. 因此, scull 省略它们. 内核使用 read 和 write 来模拟它们, 最终结果是相同的.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch03s06.html">上一页</a>&#160;</td><td width="20%" align="center"><a accesskey="u" href="ch03.html">上一级</a></td><td width="40%" align="right">&#160;<a accesskey="n" href="ch03s08.html">下一页</a></td></tr><tr><td width="40%" align="left" valign="top">3.6.&#160;scull 的内存使用&#160;</td><td width="20%" align="center"><a accesskey="h" href="index.html">起始页</a></td><td width="40%" align="right" valign="top">&#160;3.8.&#160;使用新设备</td></tr></table></div></body></html><div style="display:none"><script language="JavaScript" src="script.js"></script> </div>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -