QNX 4 Interprocess Communication (IPC)

Gamma: Version 4.0
Prev | Chapter 13. Special Topics | Next

# 13.2. QNX 4 Interprocess Communication (IPC)

QNX 4 interprocess communication is a popular mechanism for 'talking' between software modules, based on the QNX 4 operating system. QNX 4's microkernel architecture implements message passing in such a way that only data locations are transferred between processes, making its IPC for small amounts of data as, or more, efficient than shared memory schemes. Gamma encapsulates most of the common QNX 4 IPC 'C' function calls.

Functions such as `qnx_receive` and `qnx_reply` may be redundant in a program that is using one of Gamma's built-in event-loop mechanisms. To review the built-in functionality of Gamma's event loops refer to the section on event loops.

The `qnx_name_attach` function attaches a 'name' to the current process. Names, rather than PIDs, are convenient ways to look for tasks since they are static while the PID of a program will not be.

Names are ASCII strings up to 32 character in length and can be either local or global. Local names must be unique to the node. Any attempt to register an existing local name will fail. Global names allow duplication and start with a slash '/' character. Global names are stored within a name datahub in QNX 4 called nameloc. When one process wants to look up another process's name, the `qnx_name_locate` function is called and the name to PID mapping is completed.

        Gamma> myname = qnx_name_attach(0,"my_app");
        20

The first argument to the `qnx_name_attach` function is the node on which to register the name. If the node number is zero the local node is assumed. `qnx_name_attach` returns a name id which is used with the `qnx_name_detach` function.

The `qnx_name_detach` function removes a local or global name from the local name list or global datahub.

        Gamma> qnx_name_detach(0,myname);
        t

As with the `qnx_name_attach` function, the first argument to the `qnx_name_detach` function is the node number. The second argument must be the name id returned when attaching the name.

Once a name is registered then the `qnx_name_locate` function is useful for locating the task by name. The return value of this function is a dotted list of the format: `(pid . copies)` The pid is the process ID of the located task and copies is the number of processes that matched the name. Local names must be unique but there can be multiple instances of global names (those starting with '/').

An example of using the `qnx_name_locate` function follows:

        Gamma> queue = qnx_name_locate(0,"qserve",0);
        (91 . 1)

The PID of the qserve task is 91 and there was a single instance of that registered name found.It is important to assign the return value of the `qnx_name_locate` function to a variable since it is the first number in the list (PID) that is used as an argument to Gamma functions such as `qnx_send`, `qnx_receive`, `qnx_reply`, `qnx_vc_attach`, `and qnx_vc_detach`.

The `qnx_receive` function allows for the Gamma engine to remain receive-blocked on a specific PID, waiting for a message.

IMPORTANT: If Gamma is being run using a built-in event loop or using the `next_event` or `next_event_nb` functions then using the `qnx_receive` function MAY BE REDUNDANT. Event loops in Gamma have a built-in receive/reply mechanism.

The `qnx_send` function uses the QNX 4 `send` C/C++ function to send information between tasks. The `qnx_send` function is a synchronous IPC function, and as such, the sending task waits for the receiving task's reply before continuing.

The `qnx_send` function can be used to send Gamma expressions between Gamma modules. Gamma ships with a number of example programs, of which example 12 demonstrates the use of `qnx_send` to transmit and execute a function on another module. (Examples can be found in /usr/cogent/examples/ directory)

The important excerpts from this example are:

        task = car (qnx_name_locate (0, "gui", 1000));
        qnx_send (task, stringc (#Arc.fill_color = PgRGB(0xff, 0xff, 0)));
        function TitleClock()
        {
            win.title = date();
        }
        // Transmit new function
        qnx_send (task, stringc (TitleClock));
        // Execute new function once.
        qnx_send (task, stringc (#TitleClock()));

The communications channel is opened by locating the task using the `qnx_name_locate` function and then using `qnx_send`. The first `qnx_send` sends a command for the receiving task to evaluate, in this case to change the fill color of an object named 'Arc'. The `stringc` function is used to produce an expression that is parse-able.

Next, a new function is defined, passed, and executed on the other task using two separate `qnx_send`'s.

If you are sending IPC messages to a non-Cogent IPC task the `send_string` and `send_string_async` functions should be used.

Prev | Home | Next
Special Topics | Up | Cogent IPC

Copyright 1995-2002 by Cogent Real-Time Systems, Inc.