122 lines
15 KiB
HTML
122 lines
15 KiB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>The Be Book - System Overview - The Kernel Kit</title><link rel="stylesheet" href="be_book.css" type="text/css" media="all" /><link rel="shortcut icon" type="image/vnd.microsoft.icon" href="./images/favicon.ico" /><!--[if IE]>
|
||
<link rel="stylesheet" type="text/css" href="be_book_ie.css" />
|
||
<![endif]--><meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /><meta name="keywords" content="Access, BeOS, BeBook, API" /><link rel="start" href="index.html" title="The Be Book" /><link rel="up" href="TheKernelKit_Overview.html" title="The Kernel Kit" /><link rel="prev" href="TheKernelKit_ThreadsAndTeams_Overview.html" title="Threads And Teams" /><link rel="next" href="TheKernelKit_Semaphores_Overview.html" title="Semaphores" /></head><body><div id="header"><div id="headerT"><div id="headerTL"><a accesskey="p" href="TheKernelKit_ThreadsAndTeams_Overview.html" title="Threads And Teams"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a accesskey="u" href="TheKernelKit_Overview.html" title="The Kernel Kit"><img src="./images/navigation/up.png" alt="Up" /></a> <a accesskey="n" href="TheKernelKit_Semaphores_Overview.html" title="Semaphores"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="headerTR"><div id="navigpeople"><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div><div class="navigboxed" id="navigindex"><a accesskey="i" href="ClassIndex.html" title="Index">I</a></div><div class="navigboxed" id="naviglang" title="English">en</div></div><div id="headerTC">The Be Book - System Overview - The Kernel Kit</div></div><div id="headerB">Prev: <a href="TheKernelKit_ThreadsAndTeams_Overview.html">Threads And Teams</a> Up: <a href="TheKernelKit_Overview.html">The Kernel Kit</a> Next: <a href="TheKernelKit_Semaphores_Overview.html">Semaphores</a></div><hr /></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="TheKernelKit_Ports_Overview"></a>Ports</h2></div></div></div><p>A port is a system-wide message repository into which any thread can copy
|
||
a buffer of data, and from which any thread can then retrieve the buffer.
|
||
This repository is implemented as a first-in/first-out message queue: A
|
||
port stores its messages in the order in which they're received, and it
|
||
relinquishes them in the order in which they're stored. Each port has its
|
||
own message queue.</p><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="Ports_CreatingAndDestroyingAPort"></a>Creating and Destroying a Port</h3></div></div></div><p>The
|
||
<a class="link" href="TheKernelKit_Ports.html#create_port" title="create_port()"><code class="function">create_port()</code></a>
|
||
function creates a new port and assigns it a unique,
|
||
system-wide <span class="type">port_id</span> number. Although ports are accessible to all threads,
|
||
the <span class="type">port_id</span> numbers aren't disseminated by the operating
|
||
system—there's no "find_port" function. If you create a port and
|
||
want some other thread to be able to write to or read from it, you have
|
||
to broadcast the <span class="type">port_id</span> number to that thread.</p><p>A port is owned by the team in which it was created. When a team dies
|
||
(when all its threads are killed), the ports that belong to the team are
|
||
deleted. A team can bestow ownership of its ports to some other team
|
||
through the
|
||
<a class="link" href="TheKernelKit_Ports.html#set_port_owner" title="set_port_owner()"><code class="function">set_port_owner()</code></a>
|
||
function.</p><p>If you want explicitly get rid of a port, you call
|
||
<a class="link" href="TheKernelKit_Ports.html#delete_port" title="delete_port()"><code class="function">delete_port()</code></a>. You can
|
||
delete any port, not just those that are owned by the team of the calling
|
||
thread. When you delete a port, all of its unread messages are thrown
|
||
away. If you want to read this messages, but you don't want any new
|
||
messages to arrive in the meantime, you should call
|
||
<a class="link" href="TheKernelKit_Ports.html#close_port" title="close_port()"><code class="function">close_port()</code></a> before
|
||
deleting the port. Note that you can't reopen a closed port; after you
|
||
get done reading the port's messages, you're expected to delete the port.</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="Ports_TheMessageQueue"></a>The Message Queue: Reading and Writing Port Messages</h3></div></div></div><p>The length of a port's message queue—the number of messages that it
|
||
can hold at a time—is set when the port is created.</p><p>The functions
|
||
<a class="link" href="TheKernelKit_Ports.html#write_port" title="write_port(), write_port_etc()"><code class="function">write_port()</code></a> and
|
||
<a class="link" href="TheKernelKit_Ports.html#read_port" title="read_port(), read_port_etc()"><code class="function">read_port()</code></a>
|
||
manipulate a port's message queue:
|
||
<a class="link" href="TheKernelKit_Ports.html#write_port" title="write_port(), write_port_etc()"><code class="function">write_port()</code></a>
|
||
places a message at the tail of the port's message queue;
|
||
<a class="link" href="TheKernelKit_Ports.html#read_port" title="read_port(), read_port_etc()"><code class="function">read_port()</code></a>
|
||
removes the message at the head of the queue and
|
||
returns it the caller.
|
||
<a class="link" href="TheKernelKit_Ports.html#write_port" title="write_port(), write_port_etc()"><code class="function">write_port()</code></a>
|
||
blocks if the queue is full; it returns when room is made in the
|
||
queue by an invocation of
|
||
<a class="link" href="TheKernelKit_Ports.html#read_port" title="read_port(), read_port_etc()"><code class="function">read_port()</code></a>.
|
||
Similarly, if the queue is empty,
|
||
<a class="link" href="TheKernelKit_Ports.html#read_port" title="read_port(), read_port_etc()"><code class="function">read_port()</code></a>
|
||
blocks until
|
||
<a class="link" href="TheKernelKit_Ports.html#write_port" title="write_port(), write_port_etc()"><code class="function">write_port()</code></a>
|
||
is called.</p><p>You can provide a timeout for your port-writing and port-reading
|
||
operations by using the "full-blown" functions
|
||
<a class="link" href="TheKernelKit_Ports.html#write_port_etc"><code class="function">write_port_etc()</code></a> and
|
||
<a class="link" href="TheKernelKit_Ports.html#read_port_etc"><code class="function">read_port_etc()</code></a>.
|
||
By supplying a timeout, you can ensure that your port
|
||
operations won't block forever.</p><p>Although each port has its own message queue, all ports share a global
|
||
"queue slot" pool—there are only so many message queue slots that
|
||
can be used by all ports taken cumulatively. If too many port queues are
|
||
allowed to fill up, the slot pool will drain, which will cause
|
||
write_port() calls on less-than-full ports to block. To avoid this
|
||
situation, you should make sure that your write_port() and read_port()
|
||
calls are reasonably balanced.</p><p>The
|
||
<a class="link" href="TheKernelKit_Ports.html#write_port" title="write_port(), write_port_etc()"><code class="function">write_port()</code></a> and
|
||
<a class="link" href="TheKernelKit_Ports.html#read_port" title="read_port(), read_port_etc()"><code class="function">read_port()</code></a>
|
||
functions are the only way to traverse a
|
||
port's message queue. There's no notion of "peeking" at the queue's
|
||
unread messages, or of erasing messages that are in the queue.</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="Ports_PortMessages"></a>Port Messages</h3></div></div></div><p>A port message—the data that's sent through a port—consists
|
||
of a "message code" and a "message buffer." Either of these elements can
|
||
be used however you like, but they're intended to fit these purposes:</p><ul class="itemizedlist"><li><p>The message code (a single four-byte value) should be a mask, flag,
|
||
or other predictable value that gives a general representation of the
|
||
flavor or import of the message. For this to work, the sender and
|
||
receiver of the message must agree on the meanings of the values that
|
||
the code can take.</p></li><li><p>The data in the message buffer can elaborate upon the code, identify
|
||
the sender of the message, or otherwise supply additional information.
|
||
The length of the buffer isn't restricted. To get the length of the
|
||
message buffer that's at the head of a port's queue, you call the
|
||
<a class="link" href="TheKernelKit_Ports.html#port_buffer_size" title="port_buffer_size(), port_buffer_size_etc()"><code class="function">port_buffer_size()</code></a>
|
||
function.</p></li></ul><p>The message that you pass to
|
||
<a class="link" href="TheKernelKit_Ports.html#write_port" title="write_port(), write_port_etc()"><code class="function">write_port()</code></a>
|
||
is copied into the port. After
|
||
<a class="link" href="TheKernelKit_Ports.html#write_port" title="write_port(), write_port_etc()"><code class="function">write_port()</code></a>
|
||
returns, you may free the message data without affecting the
|
||
copy that the port holds.</p><p>When you read a port, you have to supply a buffer into which the port
|
||
mechanism can copy the message. If the buffer that you supply isn't large
|
||
enough to accommodate the message, the unread portion will be
|
||
lost—the next call to
|
||
<a class="link" href="TheKernelKit_Ports.html#read_port" title="read_port(), read_port_etc()"><code class="function">read_port()</code></a>
|
||
won't finish reading the message.</p><p>You typically allocate the buffer that you pass to
|
||
<a class="link" href="TheKernelKit_Ports.html#read_port" title="read_port(), read_port_etc()"><code class="function">read_port()</code></a>
|
||
by first calling
|
||
<a class="link" href="TheKernelKit_Ports.html#port_buffer_size" title="port_buffer_size(), port_buffer_size_etc()"><code class="function">port_buffer_size()</code></a>,
|
||
as shown below:</p><pre class="programlisting example c"><span class="type">char *</span><code class="varname">buf</code> = <code class="constant">NULL</code>;
|
||
<span class="type">ssize_t</span> <code class="varname">size</code>;
|
||
<span class="type">int32</span> <code class="varname">code</code>;
|
||
|
||
<span class="comment">/* We'll assume that my_port is valid.
|
||
* port_buffer_size() will block until a message shows up.
|
||
*/</span>
|
||
if ((<code class="varname">size</code> = <code class="function">port_buffer_size</code>(<code class="varname">my_port</code>)) < <code class="constant">B_OK</code>)
|
||
<span class="comment">/* Handle the error */</span>
|
||
|
||
if (<code class="varname">size</code> > 0)
|
||
<code class="varname">buf</code> = (<span class="type">char *</span>)<code class="function">malloc</code>(<code class="varname">size</code>);
|
||
|
||
if (<code class="varname">buf</code>) {
|
||
<span class="comment">/* Now we can read the buffer. */</span>
|
||
if (<code class="function">read_port</code>(<code class="varname">my_port</code>, &<code class="varname">code</code>, (<span class="type">void *</span>)<code class="varname">buf</code>, <code class="varname">size</code>) < <code class="constant">B_OK</code>)
|
||
<span class="comment">/* Handle the error */</span></pre><p>Obviously, there's a race condition (in the example) between
|
||
<a class="link" href="TheKernelKit_Ports.html#port_buffer_size" title="port_buffer_size(), port_buffer_size_etc()"><code class="function">port_buffer_size()</code></a>
|
||
and the subsequent
|
||
<a class="link" href="TheKernelKit_Ports.html#read_port" title="read_port(), read_port_etc()"><code class="function">read_port()</code></a>
|
||
call—some other thread could read the port in the interim. If you're going to use
|
||
<a class="link" href="TheKernelKit_Ports.html#port_buffer_size" title="port_buffer_size(), port_buffer_size_etc()"><code class="function">port_buffer_size()</code></a>
|
||
as shown in the example, you shouldn't have more than
|
||
one thread reading the port at a time.</p><p>As stated in the example,
|
||
<a class="link" href="TheKernelKit_Ports.html#port_buffer_size" title="port_buffer_size(), port_buffer_size_etc()"><code class="function">port_buffer_size()</code></a>
|
||
blocks until a message shows up. If you don't want to (potentially) block forever, you should use the
|
||
<a class="link" href="TheKernelKit_Ports.html#port_buffer_size_etc"><code class="function">port_buffer_size_etc()</code></a>
|
||
version of the function. As with the other
|
||
<code class="function">…etc()</code> functions,
|
||
<a class="link" href="TheKernelKit_Ports.html#port_buffer_size_etc"><code class="function">port_buffer_size_etc()</code></a>
|
||
provides a timeout option.</p></div></div><div id="footer"><hr /><div id="footerT">Prev: <a href="TheKernelKit_ThreadsAndTeams_Overview.html">Threads And Teams</a> Up: <a href="TheKernelKit_Overview.html">The Kernel Kit</a> Next: <a href="TheKernelKit_Semaphores_Overview.html">Semaphores</a> </div><div id="footerB"><div id="footerBL"><a href="TheKernelKit_ThreadsAndTeams_Overview.html" title="Threads And Teams"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a href="TheKernelKit_Overview.html" title="The Kernel Kit"><img src="./images/navigation/up.png" alt="Up" /></a> <a href="TheKernelKit_Semaphores_Overview.html" title="Semaphores"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="footerBR"><div><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div></div><div id="footerBC"><a href="http://www.access-company.com/home.html" title="ACCESS Co."><img alt="Access Company" src="./images/access_logo.png" /></a></div></div></div><div id="licenseFooter"><div id="licenseFooterBL"><a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/" title="Creative Commons License"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by-nc-nd/3.0/88x31.png" /></a></div><div id="licenseFooterBR"><a href="./LegalNotice.html">Legal Notice</a></div><div id="licenseFooterBC"><span id="licenseText">This work is licensed under a
|
||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative
|
||
Commons Attribution-Non commercial-No Derivative Works 3.0 License</a>.</span></div></div></body></html>
|