perlfork.html

来自「perl教程」· HTML 代码 · 共 406 行 · 第 1/2 页

HTML
406
字号
<p>The <a href="../../lib/Pod/perlfunc.html#item_fork"><code>fork()</code></a> emulation will not work entirely correctly when called from
within a BEGIN block.  The forked copy will run the contents of the
BEGIN block, but will not continue parsing the source stream after the
BEGIN block.  For example, consider the following code:</p>
</dd>
<dd>
<pre>
    <span class="keyword">BEGIN</span> <span class="operator">{</span>
        <span class="keyword">fork</span> <span class="keyword">and</span> <span class="keyword">exit</span><span class="operator">;</span>          <span class="comment"># fork child and exit the parent</span>
        <span class="keyword">print</span> <span class="string">"inner\n"</span><span class="operator">;</span>
    <span class="operator">}</span>
    <span class="keyword">print</span> <span class="string">"outer\n"</span><span class="operator">;</span>
</pre>
</dd>
<dd>
<p>This will print:</p>
</dd>
<dd>
<pre>
    inner</pre>
</dd>
<dd>
<p>rather than the expected:</p>
</dd>
<dd>
<pre>
    inner
    outer</pre>
</dd>
<dd>
<p>This limitation arises from fundamental technical difficulties in
cloning and restarting the stacks used by the Perl parser in the
middle of a parse.</p>
</dd>
</li>
<dt><strong><a name="item_open_filehandles">Open filehandles</a></strong>

<dd>
<p>Any filehandles open at the time of the <a href="../../lib/Pod/perlfunc.html#item_fork"><code>fork()</code></a> will be dup()-ed.  Thus,
the files can be closed independently in the parent and child, but beware
that the dup()-ed handles will still share the same seek pointer.  Changing
the seek position in the parent will change it in the child and vice-versa.
One can avoid this by opening files that need distinct seek pointers
separately in the child.</p>
</dd>
</li>
<dt><strong><a name="item_open">Forking pipe <code>open()</code> not yet implemented</a></strong>

<dd>
<p>The <a href="#item_open"><code>open(FOO, &quot;|-&quot;)</code></a> and <a href="#item_open"><code>open(BAR, &quot;-|&quot;)</code></a> constructs are not yet
implemented.  This limitation can be easily worked around in new code
by creating a pipe explicitly.  The following example shows how to
write to a forked child:</p>
</dd>
<dd>
<pre>
    <span class="comment"># simulate open(FOO, "|-")</span>
    <span class="keyword">sub</span><span class="variable"> pipe_to_fork </span><span class="operator">(</span>$<span class="operator">)</span> <span class="operator">{</span>
        <span class="keyword">my</span> <span class="variable">$parent</span> <span class="operator">=</span> <span class="keyword">shift</span><span class="operator">;</span>
        <span class="keyword">pipe</span> <span class="keyword">my</span> <span class="variable">$child</span><span class="operator">,</span> <span class="variable">$parent</span> <span class="keyword">or</span> <span class="keyword">die</span><span class="operator">;</span>
        <span class="keyword">my</span> <span class="variable">$pid</span> <span class="operator">=</span> <span class="keyword">fork</span><span class="operator">();</span>
        <span class="keyword">die</span> <span class="string">"fork() failed: $!"</span> <span class="keyword">unless</span> <span class="keyword">defined</span> <span class="variable">$pid</span><span class="operator">;</span>
        <span class="keyword">if</span> <span class="operator">(</span><span class="variable">$pid</span><span class="operator">)</span> <span class="operator">{</span>
            <span class="keyword">close</span> <span class="variable">$child</span><span class="operator">;</span>
        <span class="operator">}</span>
        <span class="keyword">else</span> <span class="operator">{</span>
            <span class="keyword">close</span> <span class="variable">$parent</span><span class="operator">;</span>
            <span class="keyword">open</span><span class="operator">(</span><span class="variable">STDIN</span><span class="operator">,</span> <span class="string">"&lt;&amp;="</span> <span class="operator">.</span> <span class="keyword">fileno</span><span class="operator">(</span><span class="variable">$child</span><span class="operator">))</span> <span class="keyword">or</span> <span class="keyword">die</span><span class="operator">;</span>
        <span class="operator">}</span>
        <span class="variable">$pid</span><span class="operator">;</span>
    <span class="operator">}</span>
</pre>
</dd>
<dd>
<pre>
    <span class="keyword">if</span> <span class="operator">(</span><span class="variable">pipe_to_fork</span><span class="operator">(</span><span class="string">'FOO'</span><span class="operator">))</span> <span class="operator">{</span>
        <span class="comment"># parent</span>
        <span class="keyword">print</span> <span class="variable">FOO</span> <span class="string">"pipe_to_fork\n"</span><span class="operator">;</span>
        <span class="keyword">close</span> <span class="variable">FOO</span><span class="operator">;</span>
    <span class="operator">}</span>
    <span class="keyword">else</span> <span class="operator">{</span>
        <span class="comment"># child</span>
        <span class="keyword">while</span> <span class="operator">(&lt;</span><span class="variable">STDIN</span><span class="operator">&gt;)</span> <span class="operator">{</span> <span class="keyword">print</span><span class="operator">;</span> <span class="operator">}</span>
        <span class="keyword">exit</span><span class="operator">(</span><span class="number">0</span><span class="operator">);</span>
    <span class="operator">}</span>
</pre>
</dd>
<dd>
<p>And this one reads from the child:</p>
</dd>
<dd>
<pre>
    <span class="comment"># simulate open(FOO, "-|")</span>
    <span class="keyword">sub</span><span class="variable"> pipe_from_fork </span><span class="operator">(</span>$<span class="operator">)</span> <span class="operator">{</span>
        <span class="keyword">my</span> <span class="variable">$parent</span> <span class="operator">=</span> <span class="keyword">shift</span><span class="operator">;</span>
        <span class="keyword">pipe</span> <span class="variable">$parent</span><span class="operator">,</span> <span class="keyword">my</span> <span class="variable">$child</span> <span class="keyword">or</span> <span class="keyword">die</span><span class="operator">;</span>
        <span class="keyword">my</span> <span class="variable">$pid</span> <span class="operator">=</span> <span class="keyword">fork</span><span class="operator">();</span>
        <span class="keyword">die</span> <span class="string">"fork() failed: $!"</span> <span class="keyword">unless</span> <span class="keyword">defined</span> <span class="variable">$pid</span><span class="operator">;</span>
        <span class="keyword">if</span> <span class="operator">(</span><span class="variable">$pid</span><span class="operator">)</span> <span class="operator">{</span>
            <span class="keyword">close</span> <span class="variable">$child</span><span class="operator">;</span>
        <span class="operator">}</span>
        <span class="keyword">else</span> <span class="operator">{</span>
            <span class="keyword">close</span> <span class="variable">$parent</span><span class="operator">;</span>
            <span class="keyword">open</span><span class="operator">(</span><span class="variable">STDOUT</span><span class="operator">,</span> <span class="string">"&gt;&amp;="</span> <span class="operator">.</span> <span class="keyword">fileno</span><span class="operator">(</span><span class="variable">$child</span><span class="operator">))</span> <span class="keyword">or</span> <span class="keyword">die</span><span class="operator">;</span>
        <span class="operator">}</span>
        <span class="variable">$pid</span><span class="operator">;</span>
    <span class="operator">}</span>
</pre>
</dd>
<dd>
<pre>
    <span class="keyword">if</span> <span class="operator">(</span><span class="variable">pipe_from_fork</span><span class="operator">(</span><span class="string">'BAR'</span><span class="operator">))</span> <span class="operator">{</span>
        <span class="comment"># parent</span>
        <span class="keyword">while</span> <span class="operator">(&lt;</span><span class="variable">BAR</span><span class="operator">&gt;)</span> <span class="operator">{</span> <span class="keyword">print</span><span class="operator">;</span> <span class="operator">}</span>
        <span class="keyword">close</span> <span class="variable">BAR</span><span class="operator">;</span>
    <span class="operator">}</span>
    <span class="keyword">else</span> <span class="operator">{</span>
        <span class="comment"># child</span>
        <span class="keyword">print</span> <span class="string">"pipe_from_fork\n"</span><span class="operator">;</span>
        <span class="keyword">exit</span><span class="operator">(</span><span class="number">0</span><span class="operator">);</span>
    <span class="operator">}</span>
</pre>
</dd>
<dd>
<p>Forking pipe <a href="#item_open"><code>open()</code></a> constructs will be supported in future.</p>
</dd>
</li>
<dt><strong><a name="item_global_state_maintained_by_xsubs">Global state maintained by XSUBs</a></strong>

<dd>
<p>External subroutines (XSUBs) that maintain their own global state may
not work correctly.  Such XSUBs will either need to maintain locks to
protect simultaneous access to global data from different pseudo-processes,
or maintain all their state on the Perl symbol table, which is copied
naturally when <a href="../../lib/Pod/perlfunc.html#item_fork"><code>fork()</code></a> is called.  A callback mechanism that provides
extensions an opportunity to clone their state will be provided in the
near future.</p>
</dd>
</li>
<dt><strong><a name="item_interpreter_embedded_in_larger_application">Interpreter embedded in larger application</a></strong>

<dd>
<p>The <a href="../../lib/Pod/perlfunc.html#item_fork"><code>fork()</code></a> emulation may not behave as expected when it is executed in an
application which embeds a Perl interpreter and calls Perl APIs that can
evaluate bits of Perl code.  This stems from the fact that the emulation
only has knowledge about the Perl interpreter's own data structures and
knows nothing about the containing application's state.  For example, any
state carried on the application's own call stack is out of reach.</p>
</dd>
</li>
<dt><strong><a name="item_thread_2dsafety_of_extensions">Thread-safety of extensions</a></strong>

<dd>
<p>Since the <a href="../../lib/Pod/perlfunc.html#item_fork"><code>fork()</code></a> emulation runs code in multiple threads, extensions
calling into non-thread-safe libraries may not work reliably when
calling fork().  As Perl's threading support gradually becomes more
widely adopted even on platforms with a native fork(), such extensions
are expected to be fixed for thread-safety.</p>
</dd>
</li>
</dl>
<p>
</p>
<hr />
<h1><a name="bugs">BUGS</a></h1>
<ul>
<li>
<p>Having pseudo-process IDs be negative integers breaks down for the integer
<code>-1</code> because the <a href="#item_wait"><code>wait()</code></a> and <a href="../../lib/Pod/perlfunc.html#item_waitpid"><code>waitpid()</code></a> functions treat this number as
being special.  The tacit assumption in the current implementation is that
the system never allocates a thread ID of <code>1</code> for user threads.  A better
representation for pseudo-process IDs will be implemented in future.</p>
</li>
<li>
<p>In certain cases, the OS-level handles created by the pipe(), socket(),
and <a href="../../lib/Pod/perlfunc.html#item_accept"><code>accept()</code></a> operators are apparently not duplicated accurately in
pseudo-processes.  This only happens in some situations, but where it
does happen, it may result in deadlocks between the read and write ends
of pipe handles, or inability to send or receive data across socket
handles.</p>
</li>
<li>
<p>This document may be incomplete in some respects.</p>
</li>
</ul>
<p>
</p>
<hr />
<h1><a name="author">AUTHOR</a></h1>
<p>Support for concurrent interpreters and the <a href="../../lib/Pod/perlfunc.html#item_fork"><code>fork()</code></a> emulation was implemented
by ActiveState, with funding from Microsoft Corporation.</p>
<p>This document is authored and maintained by Gurusamy Sarathy
&lt;<a href="mailto:gsar@activestate.com">gsar@activestate.com</a>&gt;.</p>
<p>
</p>
<hr />
<h1><a name="see_also">SEE ALSO</a></h1>
<p><a href="../../lib/Pod/perlfunc.html#fork">fork in the perlfunc manpage</a>, <a href="../../lib/Pod/perlipc.html">the perlipc manpage</a></p>

</body>

</html>

⌨️ 快捷键说明

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