📄 basic_read_write_functions.html
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head> <title></title> <link rel="stylesheet" media="screen" type="text/css" href="./style.css" /> <link rel="stylesheet" media="screen" type="text/css" href="./design.css" /> <link rel="stylesheet" media="print" type="text/css" href="./print.css" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><a href=start.html>start</a></br><h3><a name="device_driver_..._read_write_functions" id="device_driver_..._read_write_functions">Device Driver ... Read/Write Functions</a></h3><div class="level3"><p> These functions are used to read and write data to a device. The kernel system call adds two extra parameters (filep and loff_t) to the original user call.</p><p> In the following examples the device driver will read and write to a small buffer in kernel space to simulate data transfer to an actual device.</p><pre class="code c"> <span class="co1">// small buffer used by our demonstration driver</span><span class="co2">#define SCMD_SIZE 32</span><span class="kw4">static</span> <span class="kw4">char</span> scmd_data<span class="br0">[</span>SCMD_SIZE<span class="br0">]</span>; </pre></div><h4><a name="read_write_parameters" id="read_write_parameters">Read/Write parameters</a></h4><div class="level4"><p>The parameters for the <strong>read</strong> and <strong>write</strong> functions are almost the same. </p><pre class="code">filep - the kernel allocated driver structure buf - the user space buffer count - the number of bytes to transfer lofft - the offset of the first byte to transfer</pre></div><h4><a name="return_value" id="return_value">Return value</a></h4><div class="level4"><p> The return value is the actual count of data written to or read from the device. <br/> For a read a return value of 0 is used to indicate that no more data is available. <br/> For a write a return value of zero indicates that no data was written.</p></div><h4><a name="driver_read_function" id="driver_read_function">Driver Read Function</a></h4><div class="level4"><p> The Read Function transfers <strong>count</strong> chars from the device into a user space buffer (buf):</p><pre class="code c"><span class="kw4">static</span> ssize_t scmd_read<span class="br0">(</span><span class="kw4">struct</span> file *filep, <span class="kw4">char</span> *buf, size_t count, loff_t * f_pos<span class="br0">)</span> <span class="br0">{</span> <span class="kw4">int</span> pos; <span class="kw4">int</span> size; pos = *f_pos; size = SCMD_SIZE; <span class="coMULTI">/* check limits */</span> <span class="kw1">if</span> <span class="br0">(</span>pos >= size<span class="br0">)</span> pos = size<span class="nu0">-1</span>; <span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>pos + count<span class="br0">)</span> >= size<span class="br0">)</span> count = <span class="br0">(</span>size - pos<span class="br0">)</span> - <span class="nu0">1</span>; <span class="coMULTI">/* copy count from kernel buffer to user space buffer */</span> <span class="coMULTI">/* copy_to_user returns 0 on success */</span> <span class="kw1">if</span> <span class="br0">(</span>copy_to_user<span class="br0">(</span>buf,&scmd_data<span class="br0">[</span>pos<span class="br0">]</span>,count<span class="br0">)</span><span class="br0">)</span> <span class="kw1">return</span> -EFAULT; pos += count; <span class="co1">//filep->f_pos = pos; // Note this is deprecated </span> *f_pos = pos; <span class="co1">// new for 2.6 Kernel </span> <span class="kw1">return</span> count; <span class="br0">}</span></pre></div><h4><a name="driver_write_function" id="driver_write_function">Driver Write Function</a></h4><div class="level4"><p> The <strong>write</strong> function transfers <strong>count</strong> chars from user space to the device </p><pre class="code c"> <span class="kw4">static</span> ssize_t scmd_write<span class="br0">(</span><span class="kw4">struct</span> file *filep, <span class="kw4">const</span> <span class="kw4">char</span> *buf, size_t count, loff_t * f_pos<span class="br0">)</span> <span class="br0">{</span> <span class="kw4">int</span> pos; <span class="kw4">int</span> size; pos = *f_pos; size = SCMD_SIZE; <span class="coMULTI">/* check limits */</span> <span class="kw1">if</span> <span class="br0">(</span>pos >= size<span class="br0">)</span> pos = size; <span class="kw1">if</span> <span class="br0">(</span><span class="br0">(</span>pos + count<span class="br0">)</span> >= size<span class="br0">)</span> count = <span class="br0">(</span>size - pos<span class="br0">)</span> - <span class="nu0">1</span>; <span class="coMULTI">/* copy count from a user space buffer to the kernel buffer */</span> <span class="coMULTI">/* copy_from_user returns 0 on success */</span> <span class="kw1">if</span> <span class="br0">(</span>copy_from_user<span class="br0">(</span>&scmd_data<span class="br0">[</span>pos<span class="br0">]</span>,buf,count<span class="br0">)</span><span class="br0">)</span> <span class="kw1">return</span> -EFAULT; pos += count; <span class="co1">//filep->f_pos = pos; // Note Deprecated </span> *f_pos = pos; <span class="co1">// new for 2.6 Kernel </span> <span class="kw1">return</span> count; <span class="br0">}</span> </pre></div><!-- SECTION [1-4457] --><h3><a name="transferring_data" id="transferring_data">Transferring Data</a></h3><div class="level3"><p> The Linux kernel provides a pair of functions to carry out data transfer between user space and kernel space.</p><p>These functions provide a check that the user space is valid.</p><p>They return the number of un copied bytes should an error in the count or buffer be detected. The driver should return such an error to the user code.</p><p>The kernel will automatically handle any page swapping required to map the user data space.</p><pre class="code c"> <span class="co1">// copy to kernel from user</span> <span class="co1">// returns number of uncopied bytes on error</span> <span class="kw4">unsigned</span> <span class="kw4">long</span> copy_from_user<span class="br0">(</span><span class="kw4">unsigned</span> <span class="kw4">long</span> kspace_to, <span class="kw4">unsigned</span> <span class="kw4">long</span> uspace_from, <span class="kw4">unsigned</span> <span class="kw4">long</span> length<span class="br0">)</span>; <span class="co1">// copy to user from kernel </span> <span class="co1">// returns number of uncopied bytes on error</span> <span class="kw4">unsigned</span> <span class="kw4">long</span> copy_to_user<span class="br0">(</span><span class="kw4">unsigned</span> <span class="kw4">long</span> uspace_to, <span class="kw4">unsigned</span> <span class="kw4">long</span> kspace_from, <span class="kw4">unsigned</span> <span class="kw4">long</span> length<span class="br0">)</span>;</pre></div><!-- SECTION [4458-] --></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -