https://wiki.tudos.org/ikiw/api.php?action=feedcontributions&user=Gilbert&feedformat=atomTUDOS-Wiki - User contributions [en]2024-03-28T11:22:56ZUser contributionsMediaWiki 1.41.0https://wiki.tudos.org/ikiw/index.php?title=User:Gilbert&diff=340User:Gilbert2012-07-26T15:39:10Z<p>Gilbert: cron</p>
<hr />
<div>* XMPP is faster than E-Mail: payload@jabber.ccc.de<br />
<br />
<br />
== cron ==<br />
* read daily one or more projects of /examples/*/*<br />
<br />
== wiki ==<br />
* pages in Category:Knowledge Base are also Orphaned Pages... why and how to fix?<br />
----<br />
<br />
== basic ipc and object registry ==<br />
* Ipc::Iostream<br />
* Util::Registry_server<><br />
* an explanation of "label" where I can link to<br />
----<br />
* wiki page<br />
* example code to show concept<br />
* /ipc_server<br />
** updated according to source code, aw<br />
** note, extract message before reusing utcb<br />
<br />
== errors and exceptions ==<br />
* wiki page<br />
* example code to show usages, links into common pkgs<br />
----<br />
* make mapping between C++ exceptions and C error codes clear (/err.h and /exceptions)<br />
<br />
== server with protocolls and stuff, clntsrv ==<br />
* look carefully over example code<br />
* wiki page<br />
* link to real world example /memmap.cc Sigma0::pager(...)<br />
----<br />
<br />
== build system ==<br />
* look at it, generate more items here<br />
----<br />
<br />
== ned ==<br />
* link all the docs<br />
----<br />
<br />
== goos ==<br />
* its a goos, omg... docs!!<br />
----</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=User:Gilbert&diff=339User:Gilbert2012-07-26T15:20:01Z<p>Gilbert: todos</p>
<hr />
<div>* XMPP is faster than E-Mail: payload@jabber.ccc.de<br />
<br />
== wiki ==<br />
* pages in Category:Knowledge Base are also Orphaned Pages... why and how to fix?<br />
----<br />
<br />
== basic ipc and object registry ==<br />
* Ipc::Iostream<br />
* Util::Registry_server<><br />
* an explanation of "label" where I can link to<br />
----<br />
* wiki page<br />
* example code to show concept<br />
* /ipc_server<br />
** updated according to source code, aw<br />
** note, extract message before reusing utcb<br />
<br />
== errors and exceptions ==<br />
* wiki page<br />
* example code to show usages, links into common pkgs<br />
----<br />
* make mapping between C++ exceptions and C error codes clear (/err.h and /exceptions)<br />
<br />
== server with protocolls and stuff, clntsrv ==<br />
* look carefully over example code<br />
* wiki page<br />
* link to real world example /memmap.cc Sigma0::pager(...)<br />
----<br />
<br />
== build system ==<br />
* look at it, generate more items here<br />
----<br />
<br />
== ned ==<br />
* link all the docs<br />
----<br />
<br />
== goos ==<br />
* its a goos, omg... docs!!<br />
----</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=Talk:L4Re_error_handling&diff=338Talk:L4Re error handling2012-07-26T12:33:57Z<p>Gilbert: internal l4re doc url has changed</p>
<hr />
<div>= DRAFT =<br />
<br />
* interresting files ./l4sys/include/err.h, ./l4util/include/assert.h, ./l4re/include/error_helper, ./l4sys/lib/src/errtostr.c, ./cxx/lib/util/src/ipc_error_str.cc, ./cxx/lib/base/include/exceptions, ./cxx/lib/base/include/std_exc_io, ./moe/server/src/exception.cc, ./moe/server/src/exception.h, many files containing "debug", ./l4sys/include/ARCH-*/kdebug.h<br />
<br />
* BD: JDB, the kernel debugger, could be relevant in so far that you could mention <tt>enter_kdebug()</tt>.<br />
** usage: enter_kdebug("some message which helps others to find this call and see some state");<br />
** enters jdb, prints this message<br />
** NO jdb documentation at this time and place (BD: do you mean there's no documentation available? The basics in [http://os.inf.tu-dresden.de/fiasco/doc/jdb.pdf http://os.inf.tu-dresden.de/fiasco/doc/jdb.pdf] are still valid.)<br />
<br />
* common types which can represent error conditions: l4_cap_idx_t, Cap, l4_msgtag_t<br />
* l4_cap_idx_t and Cap are very similar, cause Cap is a wrapper for l4_cap_idx_t<br />
** can be invalid<br />
** check l4_cap_idx_t with l4_is_invalid_cap and l4_is_valid_cap<br />
** check Cap with L4::Cap_base::is_valid<br />
** '''TODO''' where and when do we use L4::Cap_base::validate?<br />
** how to handle? log! also: don't support the feature which needs access to this capability... generally this means end the task<br />
* l4_msgtag_t<br />
** some error conditions<br />
** many methods to check for more or less specific errors<br />
** '''TODO''' talk to someone, grep code<br />
** [http://os.inf.tu-dresden.de/~l4check/l4re/doc/internal/html/group__l4__msgtag__api.html Message Tag] l4_msgtag_has_error and more<br />
** [http://os.inf.tu-dresden.de/~l4check/l4re/doc/internal/html/group__l4__ipc__err__api.html Error handling] l4_ipc_error, l4_error and more specific ones, most specific seams to be l4_ipc_error_code<br />
** how to handle: log! depends on specific error. often task configuration error, so end task or don't provide feature<br />
<br />
<br />
* [http://os.inf.tu-dresden.de/~l4check/l4re/doc/internal/html/group__l4cxx__exceptions.html C++ Exceptions]<br />
** chksys for l4_msgtag_t and long<br />
** chkcap for Cap<T><br />
** throw some L4::Base_exception<br />
** has a method returning a "human readable" string! L4::Base_exception::str<br />
** exceptions can be printed with std::ostream<br />
** you can put try { } catch(e) { std::cerr << e } in your thread functions like main<br />
** useful usage seen in mag/server/src/main.cc<br />
<br />
<br />
* ./l4sys/lib/src/errtostr.c<br />
** l4sys_errtostr(long) for L4_E* and L4_IPC_* constants<br />
* ./cxx/lib/util/src/ipc_error_str.cc<br />
** '''TODO''' too funny<br />
* '''TODO''' grep for usage</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=Talk:L4Re_error_handling&diff=337Talk:L4Re error handling2012-07-25T13:36:11Z<p>Gilbert: link to mag main.cc</p>
<hr />
<div>= DRAFT =<br />
<br />
* interresting files ./l4sys/include/err.h, ./l4util/include/assert.h, ./l4re/include/error_helper, ./l4sys/lib/src/errtostr.c, ./cxx/lib/util/src/ipc_error_str.cc, ./cxx/lib/base/include/exceptions, ./cxx/lib/base/include/std_exc_io, ./moe/server/src/exception.cc, ./moe/server/src/exception.h, many files containing "debug", ./l4sys/include/ARCH-*/kdebug.h<br />
<br />
* BD: JDB, the kernel debugger, could be relevant in so far that you could mention <tt>enter_kdebug()</tt>.<br />
** usage: enter_kdebug("some message which helps others to find this call and see some state");<br />
** enters jdb, prints this message<br />
** NO jdb documentation at this time and place (BD: do you mean there's no documentation available? The basics in [http://os.inf.tu-dresden.de/fiasco/doc/jdb.pdf http://os.inf.tu-dresden.de/fiasco/doc/jdb.pdf] are still valid.)<br />
<br />
* common types which can represent error conditions: l4_cap_idx_t, Cap, l4_msgtag_t<br />
* l4_cap_idx_t and Cap are very similar, cause Cap is a wrapper for l4_cap_idx_t<br />
** can be invalid<br />
** check l4_cap_idx_t with l4_is_invalid_cap and l4_is_valid_cap<br />
** check Cap with L4::Cap_base::is_valid<br />
** '''TODO''' where and when do we use L4::Cap_base::validate?<br />
** how to handle? log! also: don't support the feature which needs access to this capability... generally this means end the task<br />
* l4_msgtag_t<br />
** some error conditions<br />
** many methods to check for more or less specific errors<br />
** '''TODO''' talk to someone, grep code<br />
** [http://os.inf.tu-dresden.de/~l4check/l4re/doc/html/group__l4__msgtag__api.html Message Tag] l4_msgtag_has_error and more<br />
** [http://os.inf.tu-dresden.de/~l4check/l4re/doc/html/group__l4__ipc__err__api.html Error handling] l4_ipc_error, l4_error and more specific ones, most specific seams to be l4_ipc_error_code<br />
** how to handle: log! depends on specific error. often task configuration error, so end task or don't provide feature<br />
<br />
<br />
* [http://os.inf.tu-dresden.de/~l4check/l4re/doc/html/group__l4cxx__exceptions.html C++ Exceptions]<br />
** chksys for l4_msgtag_t and long<br />
** chkcap for Cap<T><br />
** throw some L4::Base_exception<br />
** has a method returning a "human readable" string! L4::Base_exception::str<br />
** exceptions can be printed with std::ostream<br />
** you can put try { } catch(e) { std::cerr << e } in your thread functions like main<br />
** useful usage seen in mag/server/src/main.cc<br />
<br />
<br />
* ./l4sys/lib/src/errtostr.c<br />
** l4sys_errtostr(long) for L4_E* and L4_IPC_* constants<br />
* ./cxx/lib/util/src/ipc_error_str.cc<br />
** '''TODO''' too funny<br />
* '''TODO''' grep for usage</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=Talk:L4Re_error_handling&diff=331Talk:L4Re error handling2012-07-06T13:06:29Z<p>Gilbert: /* DRAFT */</p>
<hr />
<div>= DRAFT =<br />
<br />
* interresting files ./l4sys/include/err.h, ./l4util/include/assert.h, ./l4re/include/error_helper, ./l4sys/lib/src/errtostr.c, ./cxx/lib/util/src/ipc_error_str.cc, ./cxx/lib/base/include/exceptions, ./cxx/lib/base/include/std_exc_io, ./moe/server/src/exception.cc, ./moe/server/src/exception.h, many files containing "debug", ./l4sys/include/ARCH-*/kdebug.h<br />
<br />
* BD: JDB, the kernel debugger, could be relevant in so far that you could mention <tt>enter_kdebug()</tt>.<br />
** usage: enter_kdebug("some message which helps others to find this call and see some state");<br />
** enters jdb, prints this message<br />
** NO jdb documentation at this time and place<br />
<br />
* common types which can represent error conditions: l4_cap_idx_t, Cap, l4_msgtag_t<br />
* l4_cap_idx_t and Cap are very similar, cause Cap is a wrapper for l4_cap_idx_t<br />
** can be invalid<br />
** check l4_cap_idx_t with l4_is_invalid_cap and l4_is_valid_cap<br />
** check Cap with L4::Cap_base::is_valid<br />
** '''TODO''' where and when do we use L4::Cap_base::validate?<br />
** how to handle? log! also: don't support the feature which needs access to this capability... generally this means end the task<br />
* l4_msgtag_t<br />
** some error conditions<br />
** many methods to check for more or less specific errors<br />
** '''TODO''' talk to someone, grep code<br />
** [http://os.inf.tu-dresden.de/~l4check/l4re/doc/html/group__l4__msgtag__api.html Message Tag] l4_msgtag_has_error and more<br />
** [http://os.inf.tu-dresden.de/~l4check/l4re/doc/html/group__l4__ipc__err__api.html Error handling] l4_ipc_error, l4_error and more specific ones, most specific seams to be l4_ipc_error_code<br />
** how to handle: log! depends on specific error. often task configuration error, so end task or don't provide feature<br />
<br />
<br />
* [http://os.inf.tu-dresden.de/~l4check/l4re/doc/html/group__l4cxx__exceptions.html C++ Exceptions]<br />
** chksys for l4_msgtag_t and long<br />
** chkcap for Cap<T><br />
** throw some L4::Base_exception<br />
** has a method returning a "human readable" string! L4::Base_exception::str<br />
** exceptions can be printed with std::ostream<br />
** you can put try { } catch(e) { std::cerr << e } in your thread functions like main<br />
<br />
<br />
* ./l4sys/lib/src/errtostr.c<br />
** l4sys_errtostr(long) for L4_E* and L4_IPC_* constants<br />
* ./cxx/lib/util/src/ipc_error_str.cc<br />
** '''TODO''' too funny<br />
* '''TODO''' grep for usage</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=Talk:L4Re_error_handling&diff=329Talk:L4Re error handling2012-07-02T18:33:29Z<p>Gilbert: draft and notes</p>
<hr />
<div>= DRAFT =<br />
<br />
* interresting files ./l4sys/include/err.h, ./l4util/include/assert.h, ./l4re/include/error_helper, ./l4sys/lib/src/errtostr.c, ./cxx/lib/util/src/ipc_error_str.cc, ./cxx/lib/base/include/exceptions, ./cxx/lib/base/include/std_exc_io, ./moe/server/src/exception.cc, ./moe/server/src/exception.h, many files containing "debug" (but Kernel Debugger is not relevant here, I think)<br />
<br />
<br />
* common types which can represent error conditions: l4_cap_idx_t, Cap, l4_msgtag_t<br />
* l4_cap_idx_t and Cap are very similar, cause Cap is a wrapper for l4_cap_idx_t<br />
** can be invalid<br />
** check l4_cap_idx_t with l4_is_invalid_cap and l4_is_valid_cap<br />
** check Cap with L4::Cap_base::is_valid<br />
** '''TODO''' where and when do we use L4::Cap_base::validate?<br />
** how to handle? log! also: don't support the feature which needs access to this capability... generally this means end the task<br />
* l4_msgtag_t<br />
** some error conditions<br />
** many methods to check for more or less specific errors<br />
** '''TODO''' talk to someone, grep code<br />
** [http://os.inf.tu-dresden.de/~l4check/l4re/doc/html/group__l4__msgtag__api.html Message Tag] l4_msgtag_has_error and more<br />
** [http://os.inf.tu-dresden.de/~l4check/l4re/doc/html/group__l4__ipc__err__api.html Error handling] l4_ipc_error, l4_error and more specific ones, most specific seams to be l4_ipc_error_code<br />
** how to handle: log! depends on specific error. often task configuration error, so end task or don't provide feature<br />
<br />
<br />
* [http://os.inf.tu-dresden.de/~l4check/l4re/doc/html/group__l4cxx__exceptions.html C++ Exceptions]<br />
** chksys for l4_msgtag_t and long<br />
** chkcap for Cap<T><br />
** throw some L4::Base_exception<br />
** has a method returning a "human readable" string! L4::Base_exception::str<br />
** exceptions can be printed with std::ostream<br />
** you can put try { } catch(e) { std::cerr << e } in your thread functions like main<br />
<br />
<br />
* ./l4sys/lib/src/errtostr.c<br />
** l4sys_errtostr(long) for L4_E* and L4_IPC_* constants<br />
* ./cxx/lib/util/src/ipc_error_str.cc<br />
** '''TODO''' too funny<br />
* '''TODO''' grep for usage</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=L4Re_simple_client_server_example&diff=328L4Re simple client server example2012-07-02T17:27:01Z<p>Gilbert: added error handling</p>
<hr />
<div>In this tutorial we implement two applications: a simple client and server that send numbers between each other and print them. On our way we focus on the purpose of the involved L4Re objects and methods.<br />
<br />
Please have a look at the complete source code, which can be found on [https://github.com/payload/l4re-simple-client-server github.com].<br />
<br />
= Overview =<br />
<br />
Our two tasks are called simple-client and simple-server. The simple-client sends a number to the simple-server, which prints the received number and sends the number multiplied by two back to the client, which then prints the received number.<br />
<br />
To do this we have to go through different steps:<br />
# '''Argument marshalling''': For sending data through an L4 channel (or: IPC gate) we use a specific memory area that is shared between the thread and the kernel: the User-Level Thread Control Block (UTCB). Arguments that shall be sent to another thread are put into the UTCB. This process is called ''marshalling''.<br />
# '''Send data''': we need to send the marshalled data to the server<br />
# '''Receiving data''': the server needs to be ready to receive data on the channel used by the client<br />
# '''Argument unmarshalling''': the server receives data into its UTCB and needs to read the number from it. This ''unmarshalling'' reverses the marshalling process.<br />
# '''Computation and reply''': the server computes the doubled number and sends a reply to the client (using the UTCB).<br />
# '''Reply processing''': The client receives the result and prints it again.<br />
<br />
We will first go through each line in the <tt>main</tt> function of the client, which puts the number into the utcb, sends it to the server, receives the answer, and prints it.<br />
<br />
Afterwards we look at the server's <tt>dispatch</tt> method, which prints the number and answers with the double of the number.<br />
<br />
Finally we see the <tt>main</tt> function of the server, which prepares the server to be ready for receiving numbers.<br />
<br />
= ned.lua =<br />
<br />
L4Re applications are typically launched by Ned using an init-style script. These scripts are written in the Lua programming language.<br />
<br />
Let's first look at the configuration file which sets up our example:<br />
<br />
<pre><br />
require("L4")<br />
<br />
local ld = L4.default_loader<br />
local channel = ld:new_channel()<br />
<br />
ld:start({<br />
caps = {<br />
my_server_side = channel:svr()<br />
},<br />
}, "rom/simple-server")<br />
ld:start({<br />
caps = {<br />
my_client_side = channel<br />
},<br />
}, "rom/simple-client")<br />
</pre><br />
<br />
* For this example we <tt>start</tt> two tasks, simple-server and simple-client. To achieve this, we call the <tt>start()</tt> method provided by the L4.default_loader object.<br />
* In order to talk to each other, the applications need to be connected by a communication channel. In L4/Fiasco.OC this channel is represented by an IPC gate kernel object. Luckily, we don't need to know about the tiny details of the kernel interface. Instead, the L4 Lua package provides us a way of creating a channel and connecting the applications to it. This is done by calling <tt>ld:new_channel()</tt>, which provides us with a Lua channel object.<br />
* To make the IPC gate accessible to the applications, the init script allows us to specify a set of ''capabilities'' that are passed to an application during startup.<br />
** Capabilities are references to kernel objects and are specified as a list of ''<tt>name = obj_ref</tt>'' pairs in a table named <tt>caps</tt> which can be passed to every call to <tt>ld:start()</tt>. Here, <tt>obj_ref</tt> is a reference to a kernel object, such as the channel we just created. <tt>name</tt> is the name that the application may at runtime use to obtain this reference.<br />
** For simple-client, we directly map the name ''my_client_side'' to the channel created previously.<br />
** For simple-server, we map ''my_server_side'' to <tt>channel:svr()</tt> which gives us the server-side end of the channel. The reason for this lies in the kernel interface, which only allows the server-side thread to attach to an IPC gate and receive messages from it, whereas other threads can only send messages through the channel.<br />
<br />
= client.cc =<br />
<br />
We now want to look at the straight forward client.<br />
<br />
<pre><br />
Cap<void> server = Env::env()->get_cap<void>("my_client_side");<br />
if (!server.is_valid())<br />
{<br />
std::cerr << "no valid cap to 'my_client_side'" << std::endl;<br />
return 1;<br />
}<br />
</pre><br />
Here, we obtain the capability selector, which we declared for the simple-client in its caps table in the <tt>ned.lua</tt> file. We use the <tt>Env::env()</tt> object, the [http://os.inf.tu-dresden.de/L4Re/doc/group__api__l4re__env.html Initial Environment] of this task set up by Ned. This object provides access to the caps table using the <tt>get_cap()</tt> function.<br />
The returned <tt>Cap</tt> will be used to refer to the communication channel we are going to send our message through.<br />
<br />
Note that <tt>get_cap</tt> can return an invalid <tt>Cap</tt> if some error occured. We want to [[L4Re error handling|check for errors]] with the call to <tt>is_valid</tt> and print a message if it isn't valid.<br />
<br />
<pre>Ipc::Iostream ios(l4_utcb());</pre><br />
The <tt>Ipc::Iostream ios</tt> is an abstraction provided by L4Re that handles marshalling and unmarshalling data into the UTCB. Furthermore, it provides methods that wrap the common IPC functionality provided by the Fiasco.OC kernel. As a parameter to constructing <tt>ios</tt> we provide the UTCB into which the <tt>Iostream</tt> should write and read the values. With <tt>l4_utcb()</tt> we get the current UTCB of the running thread.<br />
<br />
<pre>ios << n;</pre><br />
<tt>Ipc::Iostream</tt>s implement C++ stream operators to access the UTCB. This call writes the number into the UTCB at the current location as managed by <tt>ios</tt>.<br />
<br />
<pre><br />
l4_msgtag_t tag = ios.call(server.cap());<br />
if (l4_error(tag))<br />
{<br />
std::cerr << "calling server: " << l4_error(tag) << std::endl;<br />
return 1;<br />
}<br />
</pre><br />
Most of this code is error checking and reporting. The important method call is <tt>ios.call(server.cap())</tt>. <tt>call</tt> will send data and block waiting for a reply. First, it sends the data stored in the UTCB to the IPC channel we obtained a capability for. The kernel delivers this message to whatever thread is blocked waiting on the other side. The second part of <tt>call</tt> blocks the current thread and waits for a reply from the thread behind the server capability. (<tt>server.cap()</tt> simply casts the <tt>L4::Cap</tt> object into an <tt>l4_cap_idx_t</tt>, which is expected by the lower-level system call wrappers.) The thread will be unblocked if an IPC arrives, in this case the answer of the simple-server containing a number.<br />
<br />
<pre>ios >> n;</pre><br />
After the answer from server has arrived, we read the result out of it.<br />
<br />
<pre>std::cout << n << std::endl;</pre><br />
And finally we print this number. Done.<br />
<br />
= server.cc =<br />
<br />
The more complex server contains a very important pattern. It defines a <tt>Server_object</tt> which does the actual work of answering requests and a <tt>Registry_server</tt> which dispatches IPCs to different <tt>Server_object</tt>s. <tt>Server_object</tt>s allow servers to implement different services and provide them through arbitrary IPC channels. The registry keeps track of all established server objects. Upon arrival of a message it figures out, which server object is responsible for handling the request and relays the request to this object by calling its <tt>dispatch()</tt> method.<br />
<br />
== Server object ==<br />
<br />
<pre>struct SimpleServer : Server_object</pre><br />
We define our <tt>SimpleServer</tt> as a <tt>Server_object</tt> and need to implement its very simple interface.<br />
<br />
<pre>int dispatch(l4_umword_t, Ipc::Iostream &amp;ios)</pre><br />
<tt>dispatch</tt> is the only method needed to implement the interface of <tt>Server_object</tt>. We discard the first argument, cause we don't need it. The second argument is more interesting: It is an <tt>Ipc::Iostream</tt> that wraps the receiving thread's UTCB and has already been created for us by the communication framework.<br />
<br />
<pre>ios >> n;</pre><br />
We read a number from the <tt>Ipc::Iostream</tt>. Particularly <tt>sizeof(n)</tt> bytes are read from the UTCB to <tt>n</tt> from the current position and the current position is forward by this number of bytes. No we can print the number and compute the answer.<br />
* Note, that no one forces the server to read the same amount and type of data the client sent on the other side. This ''protocol'' information is left to the implementor of client and server.<br />
<br />
<pre><br />
ios << n * 2;<br />
return L4_EOK;<br />
</pre><br />
The answer is written to the UTCB and with <tt>L4_EOK</tt> we tell the communication framework that all handling was correct. The framework will thereafter send the reply to the client.<br />
<br />
== Server setup ==<br />
<br />
In our <tt>main</tt> function we set up our server and the <tt>Server_object</tt> we implemented and let the server loop forever for accepting incoming IPCs and answering them.<br />
<br />
<pre>Util::Registry_server<> server;</pre><br />
We instantiate a <tt>Registry_server</tt> which will be the heart of our server task. It maintains a registry, where objects of type <tt>Server_object</tt> are registered and implements the <tt>loop()</tt> method, which waits for incoming IPC and dispatches incoming messages between the registered <tt>Server_object</tt>s.<br />
<br />
<pre><br />
Cap<void> cap = server.registry()->register_obj(&simple_server, "my_server_side");<br />
if (!cap.is_valid())<br />
{<br />
std::cerr << "invalid cap on register_obj 'my_server_side'" << std::endl;<br />
return 1;<br />
}<br />
</pre><br />
This call registers our instance of <tt>SimpleServer</tt> in the <tt>registry()</tt> of the <tt>Registry_server</tt>. As we already saw in the <tt>ned.lua</tt> file, there is the name <tt>"my_server_side"</tt> and we use it here to say that whenever an IPC is sent to the IPC gate named <tt>"my_server_side"</tt> the IPC is forwarded to the <tt>dispatch</tt> method of <tt>simple_server</tt>.<br />
<br />
Notice that also <tt>register_obj</tt> can return an invalid <tt>Cap</tt> and we want to check and handle this case.<br />
<br />
Now we have pretty much set up everything we need to let interaction of a client and a server happen.<br />
<br />
<pre>server.loop();</pre><br />
This invokes the <tt>loop()</tt> function implemented by the communication framework. It loops forever and deals with IPCs by forwarding them to our own <tt>Server_object</tt> and sends answers back.<br />
<br />
= Conclusion =<br />
<br />
We have seen a simple setup for a client and a server task in L4Re.<br />
* On the client side, you can read and write to an UTCB through an <tt>Ipc::Iostream</tt> object. Then, you use methods like <tt>call</tt> to initiate an IPC.<br />
* On the server side, you implement <tt>Server_object</tt>s and register them in a <tt>Registry_server</tt>. Underlying communication framework magic waits for incoming messages and calls your server object's <tt>dispatch()</tt> method, which then handles the request and prepares an answer.<br />
<br />
[[Category:Knowledge Base]]</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=User:Gilbert&diff=314User:Gilbert2012-06-25T16:18:10Z<p>Gilbert: /* doxygen */ * an explanation of "label" where I can link to</p>
<hr />
<div>* XMPP is faster than E-Mail: payload@jabber.ccc.de<br />
<br />
= TODO =<br />
<br />
== wiki ==<br />
* pages in Category:Knowledge Base are also Orphaned Pages... why and how to fix?<br />
<br />
== doxygen ==<br />
* Ipc::Iostream<br />
* Util::Registry_server<><br />
* Server_object<br />
* an explanation of "label" where I can link to</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=User:Gilbert&diff=313User:Gilbert2012-06-25T14:58:06Z<p>Gilbert: /* TODO */</p>
<hr />
<div>* XMPP is faster than E-Mail: payload@jabber.ccc.de<br />
<br />
= TODO =<br />
<br />
== wiki ==<br />
* pages in Category:Knowledge Base are also Orphaned Pages... why and how to fix?<br />
<br />
== doxygen ==<br />
* Ipc::Iostream<br />
* Util::Registry_server<><br />
* Server_object</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=User:Gilbert&diff=312User:Gilbert2012-06-25T14:56:41Z<p>Gilbert: added XMPP, added todos</p>
<hr />
<div>* XMPP is faster than E-Mail: payload@jabber.ccc.de<br />
<br />
= TODO =<br />
<br />
== doxygen ==<br />
* Ipc::Iostream<br />
* Util::Registry_server<><br />
* Server_object</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=Programming&diff=311Programming2012-06-25T14:04:05Z<p>Gilbert: added link to Category:Knowledge_Base</p>
<hr />
<div>You can program for L4 using the [http://os.inf.tu-dresden.de/L4Re/doc/ L4Re ].<br />
<br />
Also look at the pages in [[:Category:Knowledge_Base]] for more example oriented information.</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=L4Re_simple_client_server_example&diff=310L4Re simple client server example2012-06-25T13:52:09Z<p>Gilbert: added category, releveled headlines</p>
<hr />
<div>We want to understand more deeply the following simple setup. A simple server and a client, which are just sending numbers between each other and print them. While writing it, we focus on the purpose of each method and object and its role in L4Re.<br />
<br />
The whole source code can be found on [https://github.com/payload/l4re-simple-client-server github.com] and you definitly have to look there for the complete files and overview.<br />
<br />
= Overview =<br />
<br />
Our two tasks are called simple-client and simple-server. The simple-client sends a number to the simple-server, which prints the received number and sends the number multiplied by two back to the client, which prints the received number also.<br />
<br />
To do this we have to go through different steps:<br />
* the number has to be put into the UTCB<br />
* we need to say, that this number should be send to the server<br />
* the server should be ready to receive the number<br />
* the number should than be send by the client<br />
* the number should be processed by the server<br />
* the doubled number should be send back<br />
* and the finally received number should be processed by the client<br />
<br />
We will first go through each line in the <tt>main</tt> function of the client, which puts the number into the utcb, sends it to the correct server, receives the answer and prints it.<br />
<br />
Afterwards we look at the <tt>dispatch</tt> method, which prints the number and answers with the double of the number.<br />
<br />
Finally we see the <tt>main</tt> function of the server, which prepares the server to be ready for receiving numbers.<br />
<br />
= ned.lua =<br />
<br />
First we look at the configuration file which sets up both tasks.<br />
<br />
<pre><br />
require("L4")<br />
local ld = L4.default_loader<br />
local channel = ld:new_channel()<br />
ld:start({<br />
caps = {<br />
my_server_side = channel:svr()<br />
},<br />
}, "rom/simple-server")<br />
ld:start({<br />
caps = {<br />
my_client_side = channel<br />
},<br />
}, "rom/simple-client")<br />
</pre><br />
<br />
For this example we <tt>start</tt> two tasks, the simple-server and simple-client task. They are connected via <tt>channel</tt>, an IPC Gate, with each other. <tt>my_server_side</tt> is the name of the capability selector in the simple-server task, which gets full access to the IPC Gate. The full access was granted cause of the <tt>svr</tt> method. The capability selector in the other task is named <tt>my_client_side</tt> and gets the least priviliges. These capability selectors are named to retrieve them later from the <tt>caps</tt> table.<br />
<br />
= client.cc =<br />
<br />
We now want to look at the straight forward client.<br />
<br />
<pre>Cap&lt;void&gt; server = Env::env()-&gt;get_cap&lt;void&gt;(&quot;my_client_side&quot;);</pre><br />
We get the capability selector, which we declared for the simple-client in its caps table in the <tt>ned.lua</tt> file. Therefor we use the <tt>Env::env()</tt> object, the [http://os.inf.tu-dresden.de/L4Re/doc/group__api__l4re__env.html Initial Environment] of this task given by Ned. With this object, we can access the caps table with <tt>get_cap</tt>. The returned <tt>Cap</tt> will be used to refer to the server, the receiver of this message.<br />
<br />
<pre>Ipc::Iostream ios(l4_utcb());</pre><br />
The <tt>Ipc::Iostream ios</tt> handles the values in the UTCB and calls the kernel for sending these values and receiving other. It is basically a wrapper around the kernel calls and around the placement of values in the UTCB. In the constructor of <tt>ios</tt> we provide the UTCB in which the <tt>Iostream</tt> should write and read the values. With <tt>l4_utcb()</tt> we get the current UTCB of the running thread.<br />
<br />
<pre>ios &lt;&lt; n;</pre><br />
This writes the number into the UTCB at the current location as managed by <tt>ios</tt>. The current location here is the first and it is moved after writing the number.<br />
<br />
<pre>ios.call(server.cap());</pre><br />
<tt>call</tt> will send and than receive data. First it sends the data stored in the UTCB to the thread were the server capability comes from. Second it blocks the current thread and makes a closed wait for the thread behind the server capability. <tt>cap()</tt> just returns the capability selector from the <tt>Cap</tt>. The thread will be unblocked if an IPC arrives, in this case the answer of the simple-server containing a number.<br />
<br />
<pre>ios &gt;&gt; n;</pre><br />
After the answer from server has arrived, we read some number out of it.<br />
<br />
<pre>cout &lt;&lt; n &lt;&lt; &quot;\n&quot;;</pre><br />
And finally we print this number. Done.<br />
<br />
= server.cc =<br />
<br />
The more complex server contains a very important pattern. It defines a <tt>Server_object</tt> which does the actual work of answering requests and a <tt>Registry_server</tt> which dispatches IPCs to different <tt>Server_object</tt>s.<br />
<br />
<pre>struct SimpleServer : Server_object</pre><br />
We define our <tt>SimpleServer</tt> as a <tt>Server_object</tt> and need to implement its very simple interface.<br />
<br />
<pre>int dispatch(l4_umword_t, Ipc::Iostream &amp;ios)</pre><br />
<tt>dispatch</tt> is the only method needed to implement the interface of <tt>Server_object</tt>. We discard the first argument, cause we don't need it. The second argument is more interesting. It is an already set up <tt>Ipc::Iostream</tt>, which points to the UTCB containing the earliear send number.<br />
<br />
<pre>ios &gt;&gt; n;</pre><br />
We can read this number. Particularly <tt>sizeof(n)</tt> bytes are read from the UTCB to <tt>n</tt> from the current position and the current position is forward by this number of bytes. No we can print the number and send the answer.<br />
<br />
<pre><br />
ios &lt;&lt; n * 2;<br />
return L4_EOK;<br />
</pre><br />
The answer is written to the UTCB and with <tt>L4_EOK</tt> we signal to the one who called <tt>dispatch</tt> that everything is alright.<br />
<br />
In our <tt>main</tt> function we set up our server and the <tt>Server_object</tt> we implemented and let the server loop forever for accepting incoming IPCs and answering them.<br />
<br />
<pre>Util::Registry_server&lt;&gt; server;</pre><br />
We instantiate a <tt>Registry_server</tt> which will be the heart of our server task. It maintains a registry, where objects of type <tt>Server_object</tt> are registered and has the <tt>loop</tt> method, which accepts an incoming IPC containing the capability selector used to identify the registered <tt>Server_object</tt>. Now the <tt>Server_object</tt> can be found in the registry and the incoming IPC can be forwarded as an <tt>Iostream</tt> to the <tt>dispatch</tt> method of the <tt>Server_object</tt>, the method above in this file.<br />
<br />
<pre>Cap&lt;void&gt; cap = server.registry()-&gt;register_obj(&amp;simple_server, &quot;my_server_side&quot;);</pre><br />
This is the call which actually registers the our instance of <tt>SimpleServer</tt> in the <tt>registry()</tt> of the <tt>Registry_server</tt>. As we already saw in the <tt>ned.lua</tt> file, there is the name <tt>&quot;my_server_side&quot;</tt> and we use it here to say that whenever an IPC is made to the IPC-Gate named <tt>&quot;my_server_side&quot;</tt> the IPC is forwarded to the <tt>dispatch</tt> method of <tt>simple_server</tt>.<br />
<br />
Now we have pretty much set up everything we need to let interaction of a client and a server happen.<br />
<br />
<pre>server.loop();</pre><br />
We can now loop forever and deal with IPCs by forwarding them to our own <tt>Server_object</tt> and send our answer back.<br />
<br />
= Conclusion =<br />
<br />
We have seen a simple setup for a client and a server task in L4Re. With <tt>Ipc::Iostream</tt> you can read and write to an UTCB. Methods like <tt>call</tt> will initiate an IPC. You automatically get an <tt>Ipc::Iostream</tt> when you implement <tt>Server_object</tt>. <tt>Server_object</tt> itself is used handle IPCs and actually do something with requests and construct answers. <tt>Registry_server</tt> bundles the loop which receives IPCs and dispatches them to different <tt>Server_object</tt>s. Adding <tt>Server_object</tt>s to the server is as simple as registering them at the <tt>Registry_server</tt>.<br />
<br />
[[Category:Knowledge Base]]</div>Gilberthttps://wiki.tudos.org/ikiw/index.php?title=L4Re_simple_client_server_example&diff=309L4Re simple client server example2012-06-25T13:41:07Z<p>Gilbert: version 1</p>
<hr />
<div>= L4Re simple client server =<br />
<br />
We want to understand more deeply the following simple setup. A simple server and a client, which are just sending numbers between each other and print them. While writing it, we focus on the purpose of each method and object and its role in L4Re.<br />
<br />
The whole source code can be found on [https://github.com/payload/l4re-simple-client-server github.com] and you definitly have to look there for the complete files and overview.<br />
<br />
=== Overview ===<br />
<br />
Our two tasks are called simple-client and simple-server. The simple-client sends a number to the simple-server, which prints the received number and sends the number multiplied by two back to the client, which prints the received number also.<br />
<br />
To do this we have to go through different steps:<br />
* the number has to be put into the UTCB<br />
* we need to say, that this number should be send to the server<br />
* the server should be ready to receive the number<br />
* the number should than be send by the client<br />
* the number should be processed by the server<br />
* the doubled number should be send back<br />
* and the finally received number should be processed by the client<br />
<br />
We will first go through each line in the <tt>main</tt> function of the client, which puts the number into the utcb, sends it to the correct server, receives the answer and prints it.<br />
<br />
Afterwards we look at the <tt>dispatch</tt> method, which prints the number and answers with the double of the number.<br />
<br />
Finally we see the <tt>main</tt> function of the server, which prepares the server to be ready for receiving numbers.<br />
<br />
=== ned.lua ===<br />
<br />
First we look at the configuration file which sets up both tasks.<br />
<br />
<pre><br />
require("L4")<br />
local ld = L4.default_loader<br />
local channel = ld:new_channel()<br />
ld:start({<br />
caps = {<br />
my_server_side = channel:svr()<br />
},<br />
}, "rom/simple-server")<br />
ld:start({<br />
caps = {<br />
my_client_side = channel<br />
},<br />
}, "rom/simple-client")<br />
</pre><br />
<br />
For this example we <tt>start</tt> two tasks, the simple-server and simple-client task. They are connected via <tt>channel</tt>, an IPC Gate, with each other. <tt>my_server_side</tt> is the name of the capability selector in the simple-server task, which gets full access to the IPC Gate. The full access was granted cause of the <tt>svr</tt> method. The capability selector in the other task is named <tt>my_client_side</tt> and gets the least priviliges. These capability selectors are named to retrieve them later from the <tt>caps</tt> table.<br />
<br />
=== client.cc ===<br />
<br />
We now want to look at the straight forward client.<br />
<br />
<pre>Cap&lt;void&gt; server = Env::env()-&gt;get_cap&lt;void&gt;(&quot;my_client_side&quot;);</pre><br />
We get the capability selector, which we declared for the simple-client in its caps table in the <tt>ned.lua</tt> file. Therefor we use the <tt>Env::env()</tt> object, the [http://os.inf.tu-dresden.de/L4Re/doc/group__api__l4re__env.html Initial Environment] of this task given by Ned. With this object, we can access the caps table with <tt>get_cap</tt>. The returned <tt>Cap</tt> will be used to refer to the server, the receiver of this message.<br />
<br />
<pre>Ipc::Iostream ios(l4_utcb());</pre><br />
The <tt>Ipc::Iostream ios</tt> handles the values in the UTCB and calls the kernel for sending these values and receiving other. It is basically a wrapper around the kernel calls and around the placement of values in the UTCB. In the constructor of <tt>ios</tt> we provide the UTCB in which the <tt>Iostream</tt> should write and read the values. With <tt>l4_utcb()</tt> we get the current UTCB of the running thread.<br />
<br />
<pre>ios &lt;&lt; n;</pre><br />
This writes the number into the UTCB at the current location as managed by <tt>ios</tt>. The current location here is the first and it is moved after writing the number.<br />
<br />
<pre>ios.call(server.cap());</pre><br />
<tt>call</tt> will send and than receive data. First it sends the data stored in the UTCB to the thread were the server capability comes from. Second it blocks the current thread and makes a closed wait for the thread behind the server capability. <tt>cap()</tt> just returns the capability selector from the <tt>Cap</tt>. The thread will be unblocked if an IPC arrives, in this case the answer of the simple-server containing a number.<br />
<br />
<pre>ios &gt;&gt; n;</pre><br />
After the answer from server has arrived, we read some number out of it.<br />
<br />
<pre>cout &lt;&lt; n &lt;&lt; &quot;\n&quot;;</pre><br />
And finally we print this number. Done.<br />
<br />
=== server.cc ===<br />
<br />
The more complex server contains a very important pattern. It defines a <tt>Server_object</tt> which does the actual work of answering requests and a <tt>Registry_server</tt> which dispatches IPCs to different <tt>Server_object</tt>s.<br />
<br />
<pre>struct SimpleServer : Server_object</pre><br />
We define our <tt>SimpleServer</tt> as a <tt>Server_object</tt> and need to implement its very simple interface.<br />
<br />
<pre>int dispatch(l4_umword_t, Ipc::Iostream &amp;ios)</pre><br />
<tt>dispatch</tt> is the only method needed to implement the interface of <tt>Server_object</tt>. We discard the first argument, cause we don't need it. The second argument is more interesting. It is an already set up <tt>Ipc::Iostream</tt>, which points to the UTCB containing the earliear send number.<br />
<br />
<pre>ios &gt;&gt; n;</pre><br />
We can read this number. Particularly <tt>sizeof(n)</tt> bytes are read from the UTCB to <tt>n</tt> from the current position and the current position is forward by this number of bytes. No we can print the number and send the answer.<br />
<br />
<pre><br />
ios &lt;&lt; n * 2;<br />
return L4_EOK;<br />
</pre><br />
The answer is written to the UTCB and with <tt>L4_EOK</tt> we signal to the one who called <tt>dispatch</tt> that everything is alright.<br />
<br />
In our <tt>main</tt> function we set up our server and the <tt>Server_object</tt> we implemented and let the server loop forever for accepting incoming IPCs and answering them.<br />
<br />
<pre>Util::Registry_server&lt;&gt; server;</pre><br />
We instantiate a <tt>Registry_server</tt> which will be the heart of our server task. It maintains a registry, where objects of type <tt>Server_object</tt> are registered and has the <tt>loop</tt> method, which accepts an incoming IPC containing the capability selector used to identify the registered <tt>Server_object</tt>. Now the <tt>Server_object</tt> can be found in the registry and the incoming IPC can be forwarded as an <tt>Iostream</tt> to the <tt>dispatch</tt> method of the <tt>Server_object</tt>, the method above in this file.<br />
<br />
<pre>Cap&lt;void&gt; cap = server.registry()-&gt;register_obj(&amp;simple_server, &quot;my_server_side&quot;);</pre><br />
This is the call which actually registers the our instance of <tt>SimpleServer</tt> in the <tt>registry()</tt> of the <tt>Registry_server</tt>. As we already saw in the <tt>ned.lua</tt> file, there is the name <tt>&quot;my_server_side&quot;</tt> and we use it here to say that whenever an IPC is made to the IPC-Gate named <tt>&quot;my_server_side&quot;</tt> the IPC is forwarded to the <tt>dispatch</tt> method of <tt>simple_server</tt>.<br />
<br />
Now we have pretty much set up everything we need to let interaction of a client and a server happen.<br />
<br />
<pre>server.loop();</pre><br />
We can now loop forever and deal with IPCs by forwarding them to our own <tt>Server_object</tt> and send our answer back.<br />
<br />
=== Conclusion ===<br />
<br />
We have seen a simple setup for a client and a server task in L4Re. With <tt>Ipc::Iostream</tt> you can read and write to an UTCB. Methods like <tt>call</tt> will initiate an IPC. You automatically get an <tt>Ipc::Iostream</tt> when you implement <tt>Server_object</tt>. <tt>Server_object</tt> itself is used handle IPCs and actually do something with requests and construct answers. <tt>Registry_server</tt> bundles the loop which receives IPCs and dispatches them to different <tt>Server_object</tt>s. Adding <tt>Server_object</tt>s to the server is as simple as registering them at the <tt>Registry_server</tt>.</div>Gilbert