Feedback Search Top Backward

RMX-OS2: An In-Depth View (Part 1)

Written by Johan Wikman

Part1 Part2 Part3 Part4


This is the first in a series of articles where I am going to describe ReMote eXecution for OS/2 - RMX-OS2, or simply RMX. In this first article I am only going to give an overview of RMX, but in the articles to follow - which I will do my best to provide at a pace of one per month - I will dig into details and present some stuff you'll find interesting (I hope :-).

Remote Execution

I've been using and programming for OS/2 ever since version 1.1. At the same time I have also used various flavors of Unix and hence also the X Windowing System.

X and PM are essentially pretty much alike: they provide an API with which graphical applications can be written. In one respect, however, X differs radically from PM (and most other windowing systems for that matter) as it allows applications to run remotely. That is, the application can run on one computer but the user can use it on another computer. The two computers can reside anywhere on a network, if necessary in different buildings or even in different countries.

This is something that OS/2 and PM does not support: an application must run on the same computer where it is used. Yes, applications can, of course, be explicitly split into client and a server parts where the two parts can run on different computers (e.g. database applications), but you cannot take an arbitrary PM application and run it on one computer and use it on another.

Running PM applications remotely is what RMX is all about.

Why would you want to do that then? Well:

  1. Remote execution allows you to run an application on the most appropriate (powerful) computer on the network, yet interact with the application where it is most convenient.
  2. Instead of being forced to have n powerful computers for n people, you can have 1 powerful computer, where resource hungry applications are run, and n - 1 less powerful (and much cheaper) computers that are used as display servers for remote applications and for running ordinary applications.
  3. Once OS/2 for PowerPC is available you can run applications on a PowerPC, yet use them on a cheap Intel.
  4. It offers a convenient way for monitoring other computers.
  5. It is simply a neat feature :-).

To be honest, the list above is slightly vapour as RMX currently is on beta level and couldn't be used in a production environment. Nevertheless, the functionality for providing the services in the list (except item 3 of course) is there.

RMX in Practice

Ok, so what does remote execution mean in practice? A PM application's structure can schematically be pictured as:


Figure 1) Schematic picture of a PM application.

The application consists of application code that more or less frequently call operating system and PM functions. All user interaction is handled through calls to PM. If we for each call to PM instead...

  1. make a packet out of the function arguments,
  2. send the packet to another computer,
  3. on the other computer extract the arguments from the packet,
  4. execute the actual function,
  5. make a packet out of the returned value,
  6. send the packet back to the other computer,
  7. extract the returned value from the packet, and
  8. return the result back to the application
...the visual appearance and interaction of the application can be moved to another computer.


Figure 2) Schematic picture of a RMX application.

In practice, each PM call (i.e., a call to a Win or Gpi function) is replaced with the following pseudo code. We ignore for the moment exactly how that replacing is done.

ReturnType WinFunction(arguments)
  Copy all arguments to a transfer buffer
  Send buffer to server

  Read buffer from server (this call blocks until there is something to read)

  Extract result
  Return result to caller

The arguments of the function is simply copied into a buffer and sent over a communications link to the server. On the server the arguments are extracted and the actual function is executed.

void winFunction()
  Read buffer from client
  Extract arguments from buffer
  Call actual PM function
  Copy return value into buffer
  Send buffer to client

The server reads the raw data, converts it into arguments of proper type and calls the actual PM function. Essentially it is a question of transparently turning local procedure calls (LPCs) into equivalent remote procedure calls (RPCs). Seems rather trivial doesn't it? In practice, however, there some rather interesting problems to be solved:

  • How can the functions be replaced without a need for a recompilation or relink?
  • It is not only the application that calls PM functions, PM calls window procedures of the application.
  • PM often reads resources from the executable. How should this be handled when the actual executable is in another computer?
  • Arguments passed by value are trivial to handle, but what about pointers?
I'll return to these questions in a later article.

Design Requirements

When I started designing RMX - which actually is a part of my Master's Thesis - I made a list of requirements that would have to be fulfilled if RMX was ever to become an product people would use.

No recompilations - if somebody would suggest to me, "Hey, if you write your application according to these fancy guidelines, then you'll get this neat remote execution feature," I wouldn't even look at the stuff. Even a relink is too much as it effectively means that only developers could use the product. Hence, an absolute design requirement was that it should be possible to run any executable remotely without a recompile or relink. (An observant reader notices that I don't rule out patching :-).

Localized cost - of course there is a performance cost involved when applications are run remotely and LPCs are replaced with RPCs. (However, this applies only to threads that call PM; non-PM threads run at the full speed of the CPU-server. The remote execution and the speed of the display-server do not influence them at all.) That cost is acceptable as long as the added value of remote execution in itself is bigger. However, it would be unacceptable if you would have to pay for the remote execution mechanism also when you run the application locally, i.e., when you run and use it on the same computer.

Any communications media - remote execution is ultimately a question of moving data between a client and a server. The entire remote execution mechanism can be built so that it does not depend on the media or actual low-level data transfer mechanism used. Hence, RMX had to be designed so that the data transfer mechanism can be replaced without a need for changes in RMX.

Optional security - remote execution opens a loophole in the security as it allows remote applications to connect to a computer and start monitoring keystrokes. In many environments a lack of security is not an issue; in others it would prevent RMX from being used. The conclusion is that security is needed, but it must be provided in such a way that different levels of security can easily be supported.

Visual appearance - it should not be possible to detect any difference between an application running remotely and an application running locally.

Simultaneous Use - it must be possible to run remote and local application side-by-side.

So, those were some of the requirements I specified before I started designing RMX.


In the following I'll show you a concrete example of how RMX is used. The basic requirement is two computers that are connected somehow. This example assumes that we are using a network that supports named pipes.

Although RMX essentially does not care what mechanism is used for transferring data between the client and server computers, it has to be told what mechanism to use. That is done by specifying an environment variable:

The value of the variable should be the name of a DLL that provides certain functionality (I'll tell exactly what in the next article). That variable usually needs to be set only once - in CONFIG.SYS - but it is quite possible to specify on a case by case basis what communications DLL to use.

An application must be marked (patched) before it can be run remotely. This has to be done only once, and it does not influence the application's normal use (apart from the requirement that certain DLLs of RMX must be present), and if need be the application can be unpatched.

rmxpatch -p -d app.exe
I'll explain the flags and describe exactly what RMXPATCH does in a later article.

Then we have the question of how to start a remote application. After all, it will be running on a computer that may physically reside quite far from the computer where we will use it. For that purpose there is RMXSTRTR.EXE and RMXSTART.EXE. RMXSTRTR.EXE is a daemon application whose only responsibility is to start remote applications upon requests from RMXSTART.EXE. Being a daemon it is usually started when the CPU-server is booted.

detach rmxstrtr.exe
Before we can start a remote application that will appear on the display-server we must start a server application that provides services to the remote application. This is also something that normally is done when the computer is booted.

start pmserver.exe
Now everything is set and we can start the remote application. Assume that \\ODIN is the network name of the CPU-server and that \\LOKE is the name of the display-server.

rmxstart \\LOKE \\ODIN app.exe
This command will start app.exe on the computer \\ODIN but the application will appear on \\LOKE. Note, in the normal case this last step is the only thing that is needed in order to start a remote application.


Ok, so that was a brief introduction to RMX. In the articles that follow I will go a lot deeper and provide a lot more details. As I haven't written those articles yet, I don't know exactly what they will contain, but the following list shows roughly what I will cover.

Low level transfer - as mentioned, the low-level transfer mechanism of data between the remote application and the display server is completely outside RMX. In this article I will thoroughly describe the mechanism along with a detailed description of the current implementation that relies on named pipes. Based on this article it should be possible to write an implementation for TCP/IP, for example.

Marking applications for remote execution - basically any 32-bit PM application can be marked for remote execution. In this article I will describe how it is done.

Starting remote applications - RMXSTRTR.EXE and RMXSTART.EXE provide the means for starting an application on a remote computer. In this article I'll describe exactly what they do and how they do it.

Protocol - when data is transferred between two processes a protocol is needed. That is also the case in RMX.

Turning LPCs into RPCs. - basically remote execution is a question of turning certain LPCs into equivalent RPCs. In this article I will describe how that is done for the OS/2 PM API.

Threads - quite a few PM program use threads and obviously they must be supported as well. How are tightly coupled threads in in two separate processes managed?

Performance - replacing LPCs with RPCs means in the context of RMX that the performance of the display updating will suffer. Fortunately, there are measures with which the perfomance penalty can be reduced.

Security - RMX offers a possibility for adding a certain level of security. In this article I will describe how a security DLL can be written.

The only thing I guarantee about this list is that the next article will be about the low-level transfer. Apart from that, the items on the list and their order may change.

As I mentioned, I developed RMX as part of my Master's Thesis. If you can't wait for the articles, drop me a note and I'll mail the thesis to you. Being a thesis it is more general than this article series will be, but on the other hand it also contains material that I won't include in the articles.

If you want to give RMX a try, keep an eye on I'll will upload the first proper beta-release real-soon-now :-). Drop me a note if you want me to notify you when that happens.

Part1 Part2 Part3 Part4