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

📄 blocking_i_o.html

📁 ADI 公司blackfin系列的用户使用文挡。
💻 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><div class="toc"><div class="tocheader toctoggle" id="toc__header">Table of Contents</div><div id="toc__inside"><ul class="toc"><li class="clear"><ul class="toc"><li class="level2"><div class="li"><span class="li"><a href="#blocking_i_o_and_wait_queues" class="toc">Blocking I/O and Wait Queues</a></span></div><ul class="toc"><li class="level3"><div class="li"><span class="li"><a href="#wake_up_races" class="toc">Wake up Races</a></span></div></li><li class="level3"><div class="li"><span class="li"><a href="#new_wait_event_solution" class="toc">New wait event solution</a></span></div></li></ul></li></ul></li></ul></div></div><h2><a name="blocking_i_o_and_wait_queues" id="blocking_i_o_and_wait_queues">Blocking I/O and Wait Queues</a></h2><div class="level2"><p> What happens if you try to read a device that has no data available? The &ldquo;default&rdquo; option is to put the calling process to sleep until data is available. The calling process will be blocked and will not return from the <strong>read</strong> system call until data becomes available. In the meantime, other processes can execute.</p><p>This default behaviour can be overridden and the  system call can be made to  return an error code (-EAGAIN) if no data or space is available.</p><p>Note <strong>interruptible_sleep_on</strong> these functions should be replaced by the newer, race free, <strong>wait_event_interruptible</strong></p><p>A process can be put to sleep by calling one of the following functions:</p><ul><li class="level1"><div class="li"> void interruptible_sleep_on(struct wait_queue_head_t *q)</div></li><li class="level1"><div class="li"> void sleep_on(struct wait_queue_head_t *q);</div></li></ul><p>Later on, the process can be awakened by using one of these functions:</p><ul><li class="level1"><div class="li"> void wake_up_interruptible(struct wait_queue_head_t *q);</div></li><li class="level1"><div class="li"> void wake_up(struct wait_queue_head_t *q);</div></li></ul><p>The <strong>wait_queue_head_t</strong> structure will need to be initialized.</p><pre class="code c">  <span class="co2">#include &lt;linux/wait.h&gt;           </span>                                      <span class="kw4">static</span> wait_queue_head_t scmd_inq;                                      init_waitqueue_head<span class="br0">&#40;</span>&amp;scmd_inq<span class="br0">&#41;</span>;</pre><p>Once set up the <strong>wait_queue</strong> can be used in the wait queue calls intended for this patr of the process.</p><p> The <strong>interruptible_sleep_on</strong> call will return if a signal is sent to the sleeping process or if another process has issued a wake_up call to the wait queue. The signal can be detected using the following sequence.</p><pre class="code c">  <span class="kw4">struct</span> wait_queue_head_t wq;         init_waitqueue_head<span class="br0">&#40;</span>&amp;wq<span class="br0">&#41;</span>;                                              interruptible_sleep_on<span class="br0">&#40;</span>&amp;wq<span class="br0">&#41;</span>;       <span class="co1">// check for a signal         </span>                                        <span class="kw1">if</span> <span class="br0">&#40;</span>signal_pending<span class="br0">&#40;</span>current<span class="br0">&#41;</span><span class="br0">&#41;</span>          <span class="kw1">return</span> -ERESTARTSYS;            <span class="co1">// no signal we were woken up </span></pre></div><!-- SECTION [1-1961] --><h3><a name="wake_up_races" id="wake_up_races">Wake up Races</a></h3><div class="level3"><p>There is an important race condition that can be introduced by these function.</p><p>Consider that you are waiting for a condition (like space available in the data buffer for a write). You detect no space and use the <strong>interruptible_sleep_on</strong> call.</p><p>Another process reads from the buffer, create the space and issues a wake_up call to members of the sleeping queue. The race occurs if the wake up call is received after you have detected the no_space condition but before you have added yourself to the wake_up queue.</p><p>The following code sequence eliminates this race condition. In addition to sleeping waiting for a wakeup a condition statement is introduced  to indicate that the event has happened. Note that since this is a <strong>macro</strong> and NOT a function, the condition can be  an expression.</p><pre class="code c">  <span class="co2">#define __wait_event_interruptible(wq, condition, ret)                  \</span>  <span class="kw1">do</span> <span class="br0">&#123;</span>                                                                    \          wait_queue_t __wait;                                            \          init_waitqueue_entry<span class="br0">&#40;</span>&amp;__wait, current<span class="br0">&#41;</span>;                         \                                                                          \          add_wait_queue<span class="br0">&#40;</span>&amp;wq, &amp;__wait<span class="br0">&#41;</span>;                                   \          <span class="kw1">for</span> <span class="br0">&#40;</span>;;<span class="br0">&#41;</span> <span class="br0">&#123;</span>                                                      \                  set_current_state<span class="br0">&#40;</span>TASK_INTERRUPTIBLE<span class="br0">&#41;</span>;                  \                  <span class="kw1">if</span> <span class="br0">&#40;</span>condition<span class="br0">&#41;</span>                                          \                          <span class="kw2">break</span>;                                          \                  <span class="kw1">if</span> <span class="br0">&#40;</span>!signal_pending<span class="br0">&#40;</span>current<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>                         \                          schedule<span class="br0">&#40;</span><span class="br0">&#41;</span>;                                     \                          <span class="kw1">continue</span>;                                       \                  <span class="br0">&#125;</span>                                                       \                  ret = -ERESTARTSYS;                                     \                  <span class="kw2">break</span>;                                                  \          <span class="br0">&#125;</span>                                                               \          current-&gt;state = TASK_RUNNING;                 remove_wait_queue<span class="br0">&#40;</span>&amp;wq, &amp;__wait<span class="br0">&#41;</span>;                                \  <span class="br0">&#125;</span> <span class="kw1">while</span> <span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span></pre><p>NOTE the do {...} while(0) wrapper will cause this code to be executed once.</p><p> The scheduler is fooled into thinking that the process is on the wait queue and waiting to be woken up. Meanwhile the process does one last check on the condition before finally using the schedule() call to put the process to sleep.</p><p>Any task changing the condition will wake this process up by changing its state to TASK_RUNNING. This will cause a subsequent call to the schedule() function to wake the task up.</p></div><!-- SECTION [1962-4933] --><h3><a name="new_wait_event_solution" id="new_wait_event_solution">New wait event solution</a></h3><div class="level3"><p>This feature is defined as an inline function in &lt;linux/sched.h&gt;. The blocking code example demonstrates the correct use of this function.</p><pre class="code">  struct wait_queue_head_t wq;                                                  init_waitqueue_head(&amp;wq);                                                    int old_count = event_count;                                                                           if (wait_event_interruptible(wq ,(old_count!=event_count))) {// NOTE no &amp; on wq     // check for a signal                                                          return -ERESTARTSYS;                                                     }                                                                           // no signal; we were woken up and event_count had changed.                                                                                                                                                                 </pre></div><!-- SECTION [4934-] --></body></html>

⌨️ 快捷键说明

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