📄 streams.doc13.html
字号:
</dd></dl><dl class="margin"><dd><p><ol class="List"><li value="1)"><a name="86919" class="autotag"> </a>A pointer to the routine responsible for updating the data structure.</li></ol></p><p><ol class="List"><li value="2)"><a name="86920" class="autotag"> </a>A pointer to the STREAMS queue that needs to be acquired exclusively.</li></ol></p><p><ol class="List"><li value="3)"><a name="86921" class="autotag"> </a>A pointer to a STREAMS message to be given to the routine passed to <b class="routine"><i class="routine">strmSyncWriteAccess</i></b><b>( )</b>. </li></ol></p></dd></dl><dl class="margin"><dd><p class="Body"><a name="86922" class="autotag"> </a>The following code fragment illustrates the use of <b class="routine"><i class="routine">strmSyncWriteAccess</i></b><b>( )</b>:</p><dl class="margin"><dd><pre class="Code2"><a name="86923" class="autotag">int xxput(pThisQueue, pThisMsg)</a><a name="86924" class="autotag">{</a><a name="86925" class="autotag"> /* preliminary code not needing exclusive access to data structure.*/</a><a name="86926" class="autotag"> ...</a><a name="86927" class="autotag"> strmSyncWriteAccess (pQueue, pMsg, functionUpdate);</a><a name="86928" class="autotag"> /*</a><a name="86929" class="autotag"> * Either no code after call to strmSyncWriteAccess(), </a><a name="86930" class="autotag"> * or code not depending on call to functionUpdate()</a><a name="86931" class="autotag"> */</a><a name="86932" class="autotag"> ...</a><a name="86933" class="autotag">}</a><a name="86934" class="autotag"></a><a name="86935" class="autotag">void functionUpdate(pQueue, pMsg)</a><a name="86936" class="autotag">{</a><a name="86937" class="autotag"> /*</a><a name="86938" class="autotag"> * Code from xxput() requiring exclusive write access goes</a><a name="86939" class="autotag"> * here.</a><a name="86940" class="autotag"> */</a><a name="86941" class="autotag"> ...</a><a name="86942" class="autotag">}</a></pre></dd></dl><p class="Body"><a name="86943" class="autotag"> </a>This mechanism allows readers of shared data to access the data without special synchronization. The overhead of locking out all readers when the shared data structure needs to be changed is handled by <b class="routine"><i class="routine">strmSyncWriteAccess</i></b><b>( )</b>. This routine operates efficiently when a small number of instances of a STREAMS component are executing. The overhead of locking out instances increases in proportion to the number of active writer buddies. In a scenario having a large number of active instances, a more refined locking mechanism is available to lower overhead; refer to <a href="streams.doc13.html#71873"><i class="title">§4.1.3.3 Updating Shared Data Using Native VxWorks Synchronization</i></a>. </p></dd></dl></dd></dl><dl class="margin"><dd><table border="0" cellpadding="3" cellspacing="0"><tr valign="top"><td valign="top" width="40"><a name="86944" class="autotag"><br></a><img border="0" alt="*" src="../../icons/note.gif"> </td><td><div class="Note"><hr><b class="symbol_UC">NOTE: </b> Remember that synchronizing with <b class="routine"><i class="routine">strmSyncWriteAccess</i></b><b>( )</b> is only necessary if the synchronization level used by the STREAMS component is <b>SQLVL_QUEUE</b> or <b>SQLVL_QUEUEPAIR</b>.<hr></div></td></tr></table></dd></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H4"><i><a name="71873" class="autotag">Updating Shared Data Using Native VxWorks Synchronization</a></i></h4></font><dl class="margin"><dd><dl class="margin"><dd><p class="Body"><a name="71874" class="autotag"> </a>WindNet STREAMS makes it possible to use VxWorks semaphores in STREAMS put and service procedures, with the following restrictions:</p></dd></dl><dl class="margin"><dd><p class="listspace"><ul class="Bullet" type="disc"><li><a name="71875" class="autotag"> </a>Semaphores can be used only in STREAMS components that have been installed with a synchronization level of <b>SQLVL_QUEUE</b> or <b>SQLVL_QUEUEPAIR. </b></li></ul></p><p class="listspace"><ul class="Bullet" type="disc"><li><a name="71876" class="autotag"> </a>Semaphores can be held only in a single put or service procedure. It is important that semaphores not be held across <b class="routine"><i class="routine">putnext</i></b><b>( )</b> calls; deadlocks can result.</li></ul></p><p class="listspace"><ul class="Bullet" type="disc"><li><a name="71877" class="autotag"> </a>Semaphores used by STREAMS components in WindNet STREAMS must be created with the option <b>SEM_DELETE_SAFE</b>.</li></ul></p></dd></dl><dl class="margin"><dd><p class="Body"><a name="82833" class="autotag"> </a>For a general discussion of VxWorks semaphores and how to use them, see the <i class="title">VxWorks Programmer's Guide: Basic OS</i>.</p></dd></dl></dd></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H3"><i><a name="71878" class="autotag">4.1.4 General Synchronization Guidelines</a></i></h4></font><dl class="margin"><dd><dl class="margin"><dd><p class="Body"><a name="71879" class="autotag"> </a>STREAMS components executed in the WindNet STREAMS environment must adhere to the following rules in order to allow for synchronization:</p></dd></dl><dl class="margin"><dd><p><ol class="List"><li value="1)"><a name="87238" class="autotag"> </a>The STREAMS routine <b class="routine"><i class="routine">putnext</i></b><b>( )</b> and put procedures in STREAMS components can be called with any queue argument (called <font face="Palatino, serif"><i class="textVariable">q</i></font>). If the queue passed as the first argument to <b class="routine"><i class="routine">putnext</i></b><b>( )</b> is the current queue (as would be normal for <b class="routine"><i class="routine">putnext</i></b><b>( )</b>), WindNet STREAMS synchronization prevents <font face="Palatino, serif"><i class="textVariable">q</i></font> and <b class="keyword">q->q_next</b> from being changed by another execution thread. If, however, the queue argument is some other queue, it is the component's responsibility to assure the validity of the queue passed to <b class="routine"><i class="routine">putnext</i></b><b>( )</b> and <b class="routine"><i class="routine">put</i></b><b>( )</b>, as well as the corresponding <b class="keyword">q->q_next </b>field for <b class="routine"><i class="routine">putnext</i></b><b>( )</b>, that is, to validate that the pointer <b>q</b> and pointer <b>q->q_next</b> do not reference a queue already closed. </li></ol></p><dl class="margin"><dd><div class="Indent"><a name="87239" class="autotag"> </a>For example, a section of code outside the STREAMS framework wishes to call a put procedure to pass a STREAMS message into a component in the middle of a stream. This is a perfectly valid operation, and WindNet STREAMS synchronization assures that it will happen properly. However, WindNet STREAMS cannot detect whether the target stream is in the middle of a close or whether the target queue argument is stale. It is the responsibility of the component's close routine to communicate with the non-STREAMS entity and to receive a positive acknowledgment back from the entity before proceeding with the close. Only through this process can the passed queue argument be guaranteed to be valid.</div><br></dd></dl><p><ol class="List"><li value="2)"><a name="71881" class="autotag"> </a>STREAMS utilities that manipulate the message queue (<b class="routine"><i class="routine">putq</i></b><b>( )</b>, <b class="routine"><i class="routine">getq</i></b><b>( )</b>, <b class="routine"><i class="routine">insq</i></b><b>( )</b>, etc.) are valid only when the queue argument refers to the current queue. Thus, it is only safe to call message queue routines from within an open, close, put, or service procedure, and only if the <font face="Palatino, serif"><i class="textVariable">q</i></font> argument is within the same synchronization scope as the <font face="Palatino, serif"><i class="textVariable">q</i></font> argument to the procedure itself<sup><a href="#foot"><b class="FootnoteMarker">1</b></a></sup>. In particular, a component cannot invoke the callback routines <b class="routine"><i class="routine">bufcall</i></b><b>( )</b> and <b class="routine"><i class="routine">esballoc</i></b><b>( )</b> from a timer, since these routines have no queue context. This restriction can be overcome by passing a queue as part of the callback routine's argument. The callback routine can then call a put procedure on this queue argument, passing a private message which the put procedure can process.</li></ol></p><p><ol class="List"><li value="3)"><a name="87255" class="autotag"> </a>Device drivers may safely call <b class="routine"><i class="routine">putq</i></b><b>( )</b>with the queue argument being the read-side queue of the bottom component on a stream (a STREAMS device). Calling <b class="routine"><i class="routine">putq</i></b><b>( )</b> from a driver is a correct method for injecting a message into a stream. This can be done safely from interrupt context: WindNet STREAMS automatically detects this use of <b class="routine"><i class="routine">putq</i></b><b>( )</b>; it returns immediately after deferring placement of the message to the queue to a background thread. This thread then invokes the STREAMS device read-side service routine to process the message. </li></ol></p><p><ol class="List"><li value="4)"><a name="87256" class="autotag"> </a>In the WindNet STREAMS implementation of <b class="routine"><i class="routine">freezestr</i></b><b>( )</b>, <b class="routine"><i class="routine">unfreezestr</i></b><b>( )</b>, <b class="routine"><i class="routine">qprocson</i></b><b>( )</b>, and <b class="routine"><i class="routine">qprocsoff</i></b><b>( )</b>, these routines are stubs which simply return. These routines are required by multiprocessor versions of SVR4 to assure single-thread execution for certain critical STREAMS activities, such as open and close processing. The synchronized access which these routines seek to provide is automatically assured by the various utilities in WindNet STREAMS, provided the rules listed in this section are followed. </li></ol></p><p><ol class="List"><li value="5)"><a name="87257" class="autotag"> </a>Direct manipulation of the <b>q_flag</b> field of the queue structure is not permitted. Although the <i class="title">UNIX System V Release 4 Programmer's Guide: STREAMS </i>prohibits direct manipulation of the <b>q_flag</b> field, some components violate this rule and are still able to run in standard SVR4 environments. Such manipulation does not work on WindNet STREAMS and may even cause system crashes.</li></ol></p></dd></dl></dd></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H3"><i><a name="87251" class="autotag">4.1.5 Synchronization of Non-Standard Plumbing Operations.</a></i></h4></font><dl class="margin"><dd><dl class="margin"><dd><p class="Body"><a name="87263" class="autotag"> </a>Occasionally, STREAMS communication paths are unorthodox and unsupported by most STREAMS environments. You can develop workarounds by altering the queue structure field <b>q_next</b> to achieve any of the sample configurations in <a href="streams.doc13.html#87424"><i class="title">Figure 15</i></a>. In a single-threaded environment, manipulating <b>q_next</b> is permitted; however, in a multi-threaded environment, like WindNet STREAMS, changing <b>q_next</b> is prohibited. WindNet STREAMS, however, enables you to build unorthodox communication paths by providing routines that synchronize access to flow control pointers. <div class="frame"><h4 class="EntityTitle"><a name="87424" class="autotag"><font face="Helvetica, sans-serif" size="-1" class="sans">Figure 15. Examples: Non-Standard <b>q_next</b> Linkages</font></a></h4><div class="CellBody"><a name="87421" class="autotag"> </a><img class="figure" border="0" alt="" src="images/streams.doc.anc13.gif"></div></div></p><p class="Body"><a name="87428" class="autotag"> </a>For example, to build a STREAMS pipe configuration, as shown in <a href="streams.doc13.html#87424"><i class="title">Figure 15</i></a>, the <b>q_next</b> write pointer of each stream must connect to the read queue of the other stream. This process of altering the <b>q_next</b> pointer is called <i class="emphasis">welding</i>. WindNet STREAMS provides the <b class="routine"><i class="routine">strmWeld</i></b><b>( )</b> routine for setting the <b class="keyword">q_next</b> pointer safely. The routine <b class="routine"><i class="routine">strmUnWeld</i></b><b>( )</b> returns <b class="keyword">q_next</b> to NULL.</p><p class="Body"><a name="87429" class="autotag"> </a>The <b class="routine"><i class="routine">strmWeld</i></b><b>( )</b> routine executes asynchronously to the caller; therefore it takes an optional callback routine as an argument and two optional arguments to be passed to the callback routine. In addition to these parameters, <b class="routine"><i class="routine">strmWeld</i></b><b>( )</b> can be passed two destination queue pointers set to the queue pointers specified in the source queue parameters. </p><p class="Body"><a name="87430" class="autotag"> </a>To continue building the streams pipe, use <b class="routine"><i class="routine">strmWeld</i></b><b>( )</b> as follows:</p><dl class="margin"><dd><pre class="Code2"><a name="87431" class="autotag">strmWeld (pWrQA,pRdQB,pWrQB,pRdQA,NULL,NULL,NULL);</a></pre></dd></dl><p class="Body"><a name="87432" class="autotag"> </a>Such a call results in the <b class="keyword">pWrQA</b> field being set to <b class="keyword">pRdQB</b>. Similarly, the <b class="keyword">pWrQB</b> field is set to <b class="library">pRdQA</b>. Use <b class="routine"><i class="routine">strmUnWeld</i></b><b>( )</b> to undo the link between Components A and B by setting the <b class="keyword">q_next</b> fields <b class="keyword">pWrQA</b> and <b class="keyword">pWrQB</b> to NULL, as follows:</p><dl class="margin"><dd><pre class="Code2"><a name="87433" class="autotag">strmUnWeld (pWrQA,pWrQB, NULL, NULL, NULL);</a></pre></dd></dl><p class="Body"><a name="87434" class="autotag"> </a>In both preceding examples, the callback routine and its two optional arguments are set to NULL. Use the callback routine if the STREAMS component requires notification that the operation has completed.</p></dd></dl></dd></dl><a name="foot"><hr></a><span class="FNM">1</span>: <span class="Footnote"><a name="71884" class="autotag"> </a>"Same scope" means that both queues reference the queue associated with the same synchronization level, for example, the read and write-side queues of a component with <b>SQVLV_QUEUEPAIR</b> synchronization.</span><p class="navbar" align="right"><a href="index.html"><img border="0" alt="[Contents]" src="../../icons/contents.gif"></a><a href="streams.doc12.html"><img border="0" alt="[Prev]" src="../../icons/prev.gif"></a><a href="streams.doc14.html"><img border="0" alt="[Next]" src="../../icons/next.gif"></a></p></body></html><!---This file generated April 10, 1998, 12:25PM PDTby WRS Documentation (jeff), Wind River Systems, Inc. conversion tool: Quadralay WebWorks Publisher 3.5.0 template: CSS Template, Jan 1998 - Jefro --->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -