haiku-website/static/legacy-docs/bebook/TheKernelKit_Ports_Overview...

122 lines
15 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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>)) &lt; <code class="constant">B_OK</code>)
<span class="comment">/* Handle the error */</span>
if (<code class="varname">size</code> &gt; 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>, &amp;<code class="varname">code</code>, (<span class="type">void *</span>)<code class="varname">buf</code>, <code class="varname">size</code>) &lt; <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>