155 lines
11 KiB
HTML
155 lines
11 KiB
HTML
|
<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<!DOCTYPE html
|
||
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
|
<html lang="en-us" xml:lang="en-us">
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
|
<meta name="security" content="public" />
|
||
|
<meta name="Robots" content="index,follow" />
|
||
|
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
|
||
|
<meta name="DC.Type" content="reference" />
|
||
|
<meta name="DC.Title" content="Descriptor passing between processes—sendmsg() and recvmsg()" />
|
||
|
<meta name="abstract" content="The ability to pass an open descriptor between jobs can lead to a new way of designing client/server applications." />
|
||
|
<meta name="description" content="The ability to pass an open descriptor between jobs can lead to a new way of designing client/server applications." />
|
||
|
<meta name="DC.Relation" scheme="URI" content="aconcepts.htm" />
|
||
|
<meta name="DC.Relation" scheme="URI" content="../apis/socketp.htm" />
|
||
|
<meta name="DC.Relation" scheme="URI" content="xdescriptors.htm" />
|
||
|
<meta name="copyright" content="(C) Copyright IBM Corporation 2001, 2006" />
|
||
|
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 2001, 2006" />
|
||
|
<meta name="DC.Format" content="XHTML" />
|
||
|
<meta name="DC.Identifier" content="cdescriptors" />
|
||
|
<meta name="DC.Language" content="en-us" />
|
||
|
<!-- All rights reserved. Licensed Materials Property of IBM -->
|
||
|
<!-- US Government Users Restricted Rights -->
|
||
|
<!-- Use, duplication or disclosure restricted by -->
|
||
|
<!-- GSA ADP Schedule Contract with IBM Corp. -->
|
||
|
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
|
||
|
<link rel="stylesheet" type="text/css" href="./ic.css" />
|
||
|
<title>Descriptor passing between processes—sendmsg() and recvmsg()</title>
|
||
|
</head>
|
||
|
<body id="cdescriptors"><a name="cdescriptors"><!-- --></a>
|
||
|
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
|
||
|
<h1 class="topictitle1">Descriptor passing between processes—<span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span></h1>
|
||
|
<div><p>The ability to pass an open descriptor between jobs can lead to
|
||
|
a new way of designing client/server applications.</p>
|
||
|
<div class="section"><p>Passing an open descriptor between jobs allows one process, typically
|
||
|
a server, to do everything that is required to obtain the descriptor (open
|
||
|
a file, establish a connection, wait for the <span class="apiname">accept()</span> API
|
||
|
to complete) and let another process, typically a worker, handle all the data
|
||
|
transfer operations as soon as the descriptor is open. This design results
|
||
|
in simpler logic for both the server and the worker jobs. This design also
|
||
|
allows different types of worker jobs to be easily supported. The server can
|
||
|
make a simple check to determine which type of worker should receive the descriptor.</p>
|
||
|
</div>
|
||
|
<div class="section"><p>Sockets provide three sets of APIs that can pass descriptors between
|
||
|
server jobs:</p>
|
||
|
<ul><li><span class="apiname">spawn()</span> <div class="note"><span class="notetitle">Note:</span> <span class="apiname">spawn()</span> is not a socket
|
||
|
API. It is supplied as part of the i5/OS™ Process-Related APIs. </div>
|
||
|
</li>
|
||
|
<li><span class="apiname">givedescriptor()</span> and <span class="apiname">takedescriptor()</span></li>
|
||
|
<li><span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span></li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div class="section"><p>The <span class="apiname">spawn()</span> API starts a new server job (often
|
||
|
called a "child job") and gives certain descriptors to that child job. If
|
||
|
the child job is already active, then the <span class="apiname">givedescriptor()</span> and <span class="apiname">takedescriptor()</span> or
|
||
|
the <span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span> APIs need
|
||
|
to be used.</p>
|
||
|
</div>
|
||
|
<div class="section"><p>However, the <span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span> APIs
|
||
|
offer many advantages over <span class="apiname">spawn()</span> and <span class="apiname">givedescriptor()</span> and <span class="apiname">takedescriptor()</span>: </p>
|
||
|
<dl><dt class="dlterm">Portability</dt>
|
||
|
<dd>The <span class="apiname">givedescriptor()</span> and <span class="apiname">takedescriptor()</span> APIs
|
||
|
are non-standard and unique to the iSeries™. If the portability of an application
|
||
|
between iSeries and UNIX<sup>®</sup> is
|
||
|
an issue, you might want to use the <span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span> APIs
|
||
|
instead.</dd>
|
||
|
<dt class="dlterm">Communication of control information</dt>
|
||
|
<dd>Often the worker job needs to know additional information
|
||
|
when it receives a descriptor, such as: <ul><li>What type of descriptor is it?</li>
|
||
|
<li>What should the worker job do with it?</li>
|
||
|
</ul>
|
||
|
<p>The <span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span> APIs
|
||
|
allow you to transfer data, which might be control information, along with
|
||
|
the descriptor; the <span class="apiname">givedescriptor()</span> and <span class="apiname">takedescriptor()</span> APIs
|
||
|
do not.</p>
|
||
|
</dd>
|
||
|
<dt class="dlterm">Performance</dt>
|
||
|
<dd>Applications that use the <span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span> APIs
|
||
|
tend to perform slightly better than those that use the <span class="apiname">givedescriptor()</span> and <span class="apiname">takedescriptor()</span> APIs
|
||
|
in three areas: <ul><li>Elapsed time</li>
|
||
|
<li>CPU utilization</li>
|
||
|
<li>Scalability</li>
|
||
|
</ul>
|
||
|
The amount of performance improvement of an application depends on the
|
||
|
extent that the application passes descriptors.</dd>
|
||
|
<dt class="dlterm">Pool of worker jobs</dt>
|
||
|
<dd>You might want to set up a pool of worker jobs so that a server can pass
|
||
|
a descriptor and only one of the jobs in the pool becomes active and receives
|
||
|
the descriptor. The <span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span> APIs
|
||
|
can be used to accomplish this by having all of the worker jobs wait on a
|
||
|
shared descriptor. When the server calls <span class="apiname">sendmsg()</span>, only
|
||
|
one of the worker jobs receives the descriptor.</dd>
|
||
|
<dt class="dlterm">Unknown worker job ID</dt>
|
||
|
<dd>The <span class="apiname">givedescriptor()</span> API requires the server job to
|
||
|
know the job identifier of the worker job. Typically the worker job obtains
|
||
|
the job identifier and transfers it over to the server job with a data queue.
|
||
|
The <span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span> do not require
|
||
|
the extra overhead to create and manage this data queue.</dd>
|
||
|
<dt class="dlterm">Adaptive server design</dt>
|
||
|
<dd>When a server is designed using the <span class="apiname">givedescriptor()</span> and <span class="apiname">takedescriptor()</span>,
|
||
|
a data queue is typically used to transfer the job identifiers from worker
|
||
|
jobs over to the server. The server then does a <span class="apiname">socket()</span>, <span class="apiname">bind()</span>, <span class="apiname">listen()</span>,
|
||
|
and an <span class="apiname">accept()</span>. When the <span class="apiname">accept()</span> API
|
||
|
is completed, the server pulls off the next available job ID from the data
|
||
|
queue. It then passes the inbound connection to that worker job. Problems
|
||
|
arise when many incoming connection requests occur at once and there are not
|
||
|
enough worker jobs available. If the data queue that contains the worker job
|
||
|
identifiers is empty, the server blocks waiting for a worker job to become
|
||
|
available, or the server creates additional worker jobs. In many environments,
|
||
|
neither of these alternatives are what you want because additional incoming
|
||
|
requests might fill the listen backlog. <p>Servers that use <span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span> APIs
|
||
|
to pass descriptors remain unhindered during heavy activity because they do
|
||
|
not need to know which worker job is going to handle each incoming connection.
|
||
|
When a server calls <span class="apiname">sendmsg()</span>, the descriptor for the incoming
|
||
|
connection and any control data are put into an internal queue for the AF_UNIX
|
||
|
socket. When a worker job becomes available, it calls <span class="apiname">recvmsg()</span> and
|
||
|
receives the first descriptor and the control data that was in
|
||
|
the queue.</p>
|
||
|
</dd>
|
||
|
<dt class="dlterm">Inactive worker job</dt>
|
||
|
<dd>The <span class="apiname">givedescriptor()</span> API requires the worker job to
|
||
|
be active while the <span class="apiname">sendmsg()</span> API does not. The job that
|
||
|
calls <span class="apiname">sendmsg()</span> does not require any information about
|
||
|
the worker job. The <span class="apiname">sendmsg()</span> API requires only that an
|
||
|
AF_UNIX socket connection has been set up. <p>An example of how the <span class="apiname">sendmsg()</span> API
|
||
|
can be used to pass a descriptor to a job that does not exist follows:</p>
|
||
|
<p>A
|
||
|
server can use the <span class="apiname">socketpair()</span> API to create a pair of
|
||
|
AF_UNIX sockets, use the <span class="apiname">sendmsg()</span> API to send a descriptor
|
||
|
over one of the AF_UNIX sockets created by <span class="apiname">socketpair()</span>,
|
||
|
and then call <span class="apiname">spawn()</span> to create a child job that inherits
|
||
|
the other end of the socket pair. The child job calls <span class="apiname">recvmsg()</span> to
|
||
|
receive the descriptor that the server passed. The child job was not active
|
||
|
when the server called <span class="apiname">sendmsg()</span>.</p>
|
||
|
</dd>
|
||
|
<dt class="dlterm">Pass more than one descriptor at a time</dt>
|
||
|
<dd>The <span class="apiname">givedescriptor()</span> and <span class="apiname">takedescriptor()</span> APIs
|
||
|
allow only one descriptor to be passed at a time. The <span class="apiname">sendmsg()</span> and <span class="apiname">recvmsg()</span> APIs
|
||
|
can be used to pass an array of descriptors.</dd>
|
||
|
</dl>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div>
|
||
|
<div class="familylinks">
|
||
|
<div class="parentlink"><strong>Parent topic:</strong> <a href="aconcepts.htm" title="Advanced socket concepts go beyond a general discussion of what sockets are and how they work. They provide ways to design socket applications for larger and more complex networks.">Advanced socket concepts</a></div>
|
||
|
</div>
|
||
|
<div class="relref"><strong>Related reference</strong><br />
|
||
|
<div><a href="xdescriptors.htm" title="The sendmsg() and recvmsg() examples show how to design a server program that uses these APIs to handle incoming connections.">Example: Pass descriptors between processes</a></div>
|
||
|
</div>
|
||
|
<div class="relinfo"><strong>Related information</strong><br />
|
||
|
<div><a href="../apis/socketp.htm">socketpair()</a></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</body>
|
||
|
</html>
|