Tutorial: OKL4 Hello World Server

We will create a simple OKL4 server, utilising IDL4 to generate code and interfaces.

Step 1: Directory structure

The files developed for our server will be located in two directories:

  • iguana/[Server Name]/ Contains server implementation

  • libs/[Server Name]/ Contains interface that clients have access to.

For our example the full structure is as following :

|--iguana (Server Side)
|    |--hello
|         |--SConscript
|         |--src
|             |--hello_server.c
|
|--libs   (Client side)
     |--hello
          |--SConscript
          |--include
          |    |--hello.h
          |    |--interface
          |           |--hello.idl4
          |--scr
               |--hello.c

Step 2: IDL4 interface

First we will write the IDL4 interface for our server. It defines the functionality that the server will provide to the clients. It will be located in libs/[Server Name]/include/interface/[Server Name].idl4

$ mkdir -r libs/hello/include/interfaces/
$ touch libs/hello/include/interface/hello.idl4

This file contains only one interface providing one function.

$ cat libs/hello/include/interface/hello.idl4
import "iguana/types.h";

[uuid(45)]
interface hello_
{
  void say_hello(void);
};

Note: It is possible to have, for a single server, several interfaces each containing several functions.

This will allow magpie to generate, amongst other things, the server loop hello_server_loop() and the hello__say_hello() functions.

Step 3: The Server

Now we will create the server according to the definitions made in the IDL4 file. This code will be in iguana/[Server Name] and this folder will contain a src directory for source files and a SConscript file to link with the compilation system.

$ ls -R iguana/hello
iguana/hello:
SConscript  src

iguana/hello/src:
hello_server.c

This code defines main and the hello__say_hello_impl functions. The latter implements the function say_hello from the previously defined hello IDL4 interface.

$ cat iguana/hello/src/hello_server.c
#include <assert.h>
#include <stdio.h>

#include <interfaces/hello_serverdecls.h>

int  main(int argc, char **argv)
{
  printf("<===== Hello Server Started =====>\n");
  hello_server_loop();
  assert(!"Shouldn't reach here\n");
}

void    hello__say_hello_impl(CORBA_Object _caller, idl4_server_environment *_env)
{
  printf("I say hello\n");
}

As we can see the main function calls hello_server_loop() which is generated by Magpie using the IDL4 file and is found in build/iguana/object/libs_hello/include/interfaces/hello_serverloop.c

We will add to this a SConscript file. We notice the definition of the server's name (OKL4_HELLO_SERVER), its priority, and the list of depending libraries.

$ cat iguana/hello/SConscript

Import("*")
weaver = env.WeaverIguanaProgramServer(server_name = "OKL4_HELLO_SERVER",
                                       priority=50)

obj = env.KengeProgram("ig_hello",
                       weaver = weaver,
                       extra_source =
args["idl_server_src"]['hello.idl4'],
                       LIBS=["c", "iguana", "l4", "l4e",
"mutex"])
Return("obj")

Step 4: The Client Side

In addition to the interface defined by the IDL4 file we will add a wrapper which provide an abstraction layer for using the server. Headers will be in libs/hello/include/ and sources in libs/hello/src/

$ cat libs/hello/include/hello.h
#ifndef __HELLO_H__
#define __HELLO_H__

void    hello_init(void);
void    say_hello(void);

#endif

$ cat libs/hello/src/hello.c

#include <iguana/env.h>
#include <iguana/memsection.h>
#include <iguana/thread.h>
#include <l4/thread.h>

#include <interfaces/hello_client.h>
#include <hello/hello.h>

static  L4_ThreadId_t server_tid;

void hello_init(void)
{
    thread_ref_t server_;

    memsection_lookup((objref_t)
                      env_memsection_base(iguana_getenv("OKL4_HELLO_SERVER")),
                      &server_);
    server_tid = thread_l4tid(server_);
}

void    say_hello(void)
{
  hello__say_hello(server_tid, NULL);
}

The main purpose of this layer is to mask the TID handling. The TID is the server's thread identifier and is necessary to communicate with it. So using the server will summarize with calling hello_init for TID initialization and then say_hello for asking the server to print.

Lastly we need a SConscript for the client side :

$ cat libs/hello/SConscript
 Import("*")
(client_headers, client_src, server_headers, server_src) = env.KengeIDL()

lib = env.KengeLibrary("hello", LIBS=["c", "iguana", "l4e"],
                       extra_headers = client_headers,
                       extra_source = client_src)

Return("lib", "server_headers", "server_src")

Step 5: Global SConscript

To allow the compilation of our server we need to add it in the main SConstruct file :

$ cat project/iguana/SConstruct
[...]
#################################
## Hello Servers
#################################
(hello_lib, hello_headers, hello_servers) = ig_env.Package("libs/hello")

iguana_hello = ig_env.Package("iguana/hello",
                               idl_server_headers = hello_headers,
idl_server_src = hello_servers)
apps += [iguana_hello]
[...]

This modification adds to “apps” the server hello, located at iguana/hello using the library libs/hello.

Step 6: Build and Simulate

We can now test if the server compile and execute smoothly.

$ ./tools/build.py machine=ia32_pc99 project=iguana wombat=True simulate
[...]
<===== Hello Server Started =====>
[...]

From this build, the compile-time copied or generated files are:

$ find build -iname "*hello*"
build/iguana/lib/libhello.a
build/iguana/ig_hello
build/iguana/ig_hello/object/src/hello_server.o
build/iguana/object/libs_hello
build/iguana/object/libs_hello/src/hello.o
build/iguana/object/libs_hello/include/interfaces/hello_serverdecls.h
build/iguana/object/libs_hello/include/interfaces/hello_client.h
build/iguana/object/libs_hello/include/interfaces/hello_serverloop.c
build/iguana/include/hello
build/iguana/include/hello/hello.h
build/iguana/include/interfaces/hello_serverdecls.h
build/iguana/include/interfaces/hello_client.h
build/iguana/include/interfaces/hello_serverloop.c
build/iguana/include/interfaces/hello_serverloop.o
build/iguana/bin/ig_hello.linkaddress
build/iguana/bin/ig_hello

Of these, the most interesting are:

  • build/iguana/lib/libhello.a: The client library for using the server

  • build/iguana/object/libs_hello/include/interfaces/hello_serverloop.c: Contains the hello_server_loop()

  • build/iguana/include/hello/hello.h: Copy of libs/hello/include/hello.h

  • build/iguana/bin/ig_hello: Our server binary

Step 7: Using the server

In order to communicate with our server using the defined interface a program must :

  • be linked with libhello.a
  • include hello/hello.h
  • initialize communication with hello_init()

Then, we can make the server print with say_hello().

Acknowledgment: Tutorial by Remy Gottschalk, via http://lists.okl4.org/pipermail/developer/2008-April/000856.html

DevelopAServer (last edited 2008-08-11 02:34:29 by localhost)