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

📄 semaphores.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><h2><a name="critical_areas" id="critical_areas">Critical Areas</a></h2><div class="level2"><p> The example device driver was not designed to allow more than a single read/ write access to the data buffer. It was attempting to simply demonstrate the mechanics of the Open/Close and Read/Write functions.</p><p>In a real world driver the resource being driven would need to have more sophisticated access control.</p><p>In the previous example each task using the device had its own position pointer and was allowed to write to the data buffer no matter what was happening with any other driver trying to access the same device.</p><p>In order to improve the example driver example the data structure needs to have the data buffer positional pointers added to it. As each task then accesses the data buffer some protection is required to prevent any other task interrupting any process using these pointers.</p><p>Consider the following sequence:</p><table class="inline">	<tr>		<td class="leftalign">Task 1                             </td><td class="leftalign">Task 2                                  </td>	</tr>	<tr>		<td class="rightalign">                                   </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="leftalign">Opens the driver for write         </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="leftalign">fetches the buffer pointer         </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td>starts to write data to the buffer </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="leftalign">reads data pointer                 </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="leftalign">blocks waiting for user data       </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="rightalign">                                   </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="rightalign">                                   </td><td class="leftalign">Runs while Task 1 is blocked            </td>	</tr>	<tr>		<td class="rightalign">                                   </td><td class="leftalign">Opens the driver for write              </td>	</tr>	<tr>		<td class="rightalign">                                   </td><td class="leftalign">fetches the buffer pointer              </td>	</tr>	<tr>		<td class="rightalign">                                   </td><td class="leftalign">Writes data to the buffer               </td>	</tr>	<tr>		<td class="rightalign">                                   </td><td>completes and updates the buffer pointer</td>	</tr>	<tr>		<td class="rightalign">                                   </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="leftalign">Task 1 Unblocks                    </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="leftalign">Completes the data write           </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="leftalign">Updates the buffer pointer         </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="rightalign">                                   </td><td class="rightalign">                                        </td>	</tr>	<tr>		<td class="leftalign">This task&rsquo;s data is in the buffer  </td><td class="leftalign">This task&rsquo;s data has been &ldquo;lost&rdquo;        </td>	</tr>	<tr>		<td class="rightalign">                                   </td><td class="rightalign">                                        </td>	</tr></table><br /><p> To stop this kind of operation some mechanism needs to be provided to prevent any other task accessing the device data pointers or the buffer while one task is trying to use the same device.</p><p>The device data buffer and its pointers is known as a Critical Area.  Once one task has access to this Critical Area other tasks need to be suspended of held until the first task has completed.</p><p>Linux offers <strong>spinlocks</strong> and <strong>semaphores</strong> to provide this sort of protection.</p><p>Since the access to user data can block, you need to use a <strong>semaphore</strong>.  Spinlocks can only be used where a task will not be blocked they are normally used on SMP systems or where data is shared with interrupt handlers.</p><p> Semaphores in Linux are defined in &lt;asm/semaphore.h&gt;. They have a type of </p><pre class="code"> struct semaphore.</pre><p> Semaphores must be initialized prior to use by passing a numeric argument to the <strong>sema_init</strong> function.  A 1 value will initialize the semaphore as full. In this state it can be taken by a call to <strong>down</strong> or <strong>down_interruptible</strong>. A 0 value will initialize the <strong>semaphore</strong> as <strong>empty</strong>. In this state it can be given by a call to <strong>up</strong>.</p><p>An example of semaphore initialization.</p><pre class="code c">        <span class="co2">#include &lt;asm/semaphore.h&gt;                            </span>                                                                      <span class="kw4">struct</span> semaphore mysem;                                                                                                     sema_init<span class="br0">&#40;</span>&amp;mysem, <span class="nu0">1</span><span class="br0">&#41;</span>; <span class="coMULTI">/* init the semaphore as full */</span></pre><p> Use <strong>down</strong> or <strong>down_interruptible</strong> to <strong>take</strong> a semaphore. If the semaphore value is 0, the function will sleep after adding itself to a list of tasks interested in any <strong>wake up</strong> call sent to the semaphore.  A task using the <strong>up</strong> function (on the same semaphore) will cause a sleeping task waiting for the semaphore to be woken up.</p><p>The <strong>down_interruptible</strong> function can be interrupted by a signal. (for example pressing control C on the keyboard). If the function <strong>down_interruptible</strong> was interrupted by a signal it will return a non zero value. This can be used, within the driver, to allow the kernel to handle the signal or pass the control back to the  user task with the signal condition flagged.</p><pre class="code c">&nbsp;     <span class="kw1">if</span> <span class="br0">&#40;</span>down_interruptible<span class="br0">&#40;</span>&amp;mysem<span class="br0">&#41;</span><span class="br0">&#41;</span>        <span class="kw1">return</span> -ERESTARTSYS;</pre><p>Put or release the semaphore with the <strong>up</strong> function:</p><pre class="code c">     up <span class="br0">&#40;</span>&amp;mysem<span class="br0">&#41;</span>;</pre><p>Here is a typical code example: </p><pre class="code c">&nbsp;  <span class="co2">#include &lt;asm/semaphore.h&gt;                               </span>  <span class="kw4">static</span> <span class="kw4">struct</span> semaphore mysem;                             ...                                                           <span class="me1">sema_init</span><span class="br0">&#40;</span>&amp;mysem, <span class="nu0">1</span><span class="br0">&#41;</span>; <span class="coMULTI">/* init the semaphore as full */</span>                                                                                                                        <span class="kw4">static</span> <span class="kw4">int</span> mydata_flag = <span class="nu0">0</span>;                                                                                           ...                                                                                                                      <span class="kw1">if</span><span class="br0">&#40;</span>down_interruptible<span class="br0">&#40;</span>&amp;mysem<span class="br0">&#41;</span><span class="br0">&#41;</span>                                <span class="kw1">return</span> -ERESTARTSYS;                                                                                               <span class="kw1">if</span> <span class="br0">&#40;</span> mydata_flag == <span class="nu0">0</span> <span class="br0">&#41;</span>   <span class="br0">&#123;</span>                                   mydata_flag = <span class="nu0">1</span>;                                           <span class="coMULTI">/* ... init data or add to a list */</span>                    <span class="br0">&#125;</span>                                                          up<span class="br0">&#40;</span>&amp;mysem<span class="br0">&#41;</span>;                                           &nbsp;</pre></div><!-- SECTION [2-] --></body></html>

⌨️ 快捷键说明

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