The INtime kernel is designed so that user applications and some system services are dynamically loaded into the environment rather than permanently linked to the kernel. A load server manages the loading of both application and dynamic libraries. This section describes the load process and the different modes in which it may be used.
There are three components involved with loading applications onto an INtime node.
Note that the relationship is the same whether the INtime kernel is an INtime for Windows node on the same host as Windows, or if it is an INtime Distributed RTOS node on a different host.
The load process performs the following steps:
The load client provides the following information to the load server to create a new process:
The system call CreateRtProcess is used by an INtime application to create a new process from an .RTA (INtime Real-Time Application) file generated by the SDK. It works in two different ways depending on which INtime product is being used.
The system call CreateRemoteRtProcess is used by an INtime application to create a new process on another node.
The process may be created "suspended" by specifying the PROC_SUSPEND flag in the flags parameter. That is, the process is created and does not run until a call is made to StartRtProcess. This call returns a handle to be used in the WaitForRtProcessEx call which causes the caller to wait for the target process to terminate and returns the exit code from the process.
A Windows application may call ntxCreateRtProcess to load an RTA onto an INtime node. The call causes the ldrta.exe client to be invoked.
Command-line arguments for the loaded application are passed to the application from the load client as a single string. The command-line arguments string is parsed and presented to the main() function in the argv array.
Arguments passed to INtime programs are strings delimited by double or single quotes and spaces. Quotes may not be quoted but single quotes may appear within double quotes and vice versa. A string terminates when a character matching the first quoting char appears. The '\' character has no special meaning.
Examples:
ABC : one argument, ABC
"ABC" : one argument, ABC
ABC 'DEF' : two arguments, ABC and DEF
"ABC" 'DEF' : two arguments, ABC DEF.
"ABC" 'DEF' GHI : three arguments, ABC DEF GHI
"ABC"'DEF' : one argument, ABCDEF
"'ABC'" : one argument, 'ABC'
'"\\A\B\C\DEF GHI\"' : one argument, \\A\B\C\DEF GHI\
"A B C" ... D E F : five argument, "A B C" ... D E F
There are a number of additional features built around the application loader to provide more product features:
The load server has a thread which responds to requests from the load client which runs at a default priority of 130. If this interferes with the operation of other threads while loading another application this can be configured to use a different priority.
In the Advanced configuration section of the configuration utility, select the section LOADER (or create a new section if it does not exist). Create a new DWORD value in this section called LOADER_PRI and set it to the desired priority.
The priority of the initial thread of the loaded application can also be configured. The default is 155, and this may be configured by creating a DWORD value called INIT_PRI in the LOADER section, and setting it to the desired priority.
When a sequence of applications is loaded by the load client, the client considers the operation is complete as soon as the new application is told to start. It can then start to load the following application in the list. This may cause problems if the second application depends on the first application for its correct operation. For example, you may wish to load a device driver process followed by an application which uses it. In this case the device driver may take some time to initialize its hardware before it is ready to be used. If the load client just loads the second application immediately after the device driver is started it may try to access the device driver before it is ready. This situation can be handled internally by the driver and the application, but there is also a general-purpose synchronization mechanism to handle this situation.
An option may be provided to the load client to cause it to wait after starting an application until that application indicates it has complete its initialization. The option also has a timeout so that if the loaded application fails to initialize the load sequence does not stop. The application in question must cooperate in this sequence by calling SynchronizeRtLoader when it has completed its initialization and is ready to service request from other applications.
When loading an application using ldrta.exe, use the -W command-line option to wait for the loaded application to call SynchronizeRtLoader. The loader will wait for 20 seconds, and then return anyway. If a different timeout is required the use the -WAIT nnnn command-line option, where nnnn is the desired timeout in milliseconds. When loading an application using CreateRtProcess specify the PROC_WAIT_FOR_INIT flag to cause the loader to wait for the default 30 seconds, or when using CreateRtProcessEx specify the PROC_WAIT_FOR_INIT_PARAM and set the desired timeout in the PROCESSATTRIBUTESEX.WaitForInit field.
Applications can synchronize on the end of a process and receive the process' exit code (the value passed to exit()) by calling WaitForRtProcess (or WaitForRtProcessEx). There are also equivalent ntxStartRtProcess and ntxWaitForRtProcess calls. Sample code for an INtime application is shown below:
Synchronizing on the end of a process |
Copy Code |
---|---|
DWORD dwFlags; // create the process with the PROC_SUSPEND flag in order to use the dwFlags = PROC_SUSPEND;
// start the process and receive the wait handle
// wait for the end of the process using the wait handle |
When an INtime for Windows node is started, there is a short time after the node starts during which the INtime Windows services (I/O services, registry, event log, etc.) are registering themselves with the new node. If, for example, an application needs to perform file I/O it should synchronize with the startup of the I/O service before attempting to open a file. To do this the application can call WaitForRtIoService before performing any file I/O. If you are loading your application from a Windows application and you wish to make sure the I/O service is properly initialized you can call ntxWaitForIoService from your Windows application.
Applications may be configured to start automatically when an INtime node is started. There is a different mechanism for doing this for each of the INtime products.
INtime for Windows has a feature called the Autoloader. This is a feature of the INtime Kernel Manager service which reads a list of applications from the Windows registry after it starts a node. For each item in the list it invokes the Windows load client. Use the INtime for Windows configuration utility to add applications to the Autoloader.
INtime Distributed RTOS has a feature called the Initial Application Loader. This is a thread which reads a list of applications from a local text file and invokes the INtime load client for each item.
Windows scripts (batch files) may be written to load a sequence of applications on an INtime node. The Windows ldrta.exe client may be used in command-line mode to perform this operation. See the ldrta.exe help for details about command-line options.
The piperta.exe command may also be used to launch applications on an INtime node. This utility launches an application, then waits for it to complete before exiting. It returns the exit code of the INtime application to the Windows script. The second function of the piperta utility is to capture the INtime application's stdin and stdout streams and redirect them to and from the piperta utility. This allows a script to capture output generated by an INtime application, for example.
A Windows application may load a real-time application by calling ntxCreateRtProcess with the name of an RTA file. Alternatively, it may store the RTA file as a binary resource inside the Windows application itself. When it wants to load the RTA it can copy the contents to a temporary file and load it. In this way a Windows .exe file and its associated .rta file can be kept as a single binary object.
Loading from an RTA resource |
Copy Code |
---|---|
// find the RTA resource if ((lpRta = LockResource(hRta)) == NULL) |
The load server can be configured to change its default behavior and that of the loaded processes. To change the default behavior for all loaded processes, find or locate the LOADER section in the Advanced configuration for the node, and add or modify values as shown in the table. The configurable parameters are as follows:
Name | Type | Default | Min | Max | Description |
INIT_PRI | DWORD | 155 | 5 | 254 | Application initial priority |
LOADER_PRI | DWORD | 130 | 5 | 254 | Load server thread priority |
RSL_DEL_TASK_PRI | DWORD | 128 | 5 | 253 | RSL object deletion thread priority |
The application loader is also involved in loading real-time shared libraries ("RSL"s). These are binary objects, similar to DLL files in Windows. They may be loaded implicitly by linking an RTA to the link library associated with the RSL, or dynamically using the LoadRtLibrary system call.
The loader is involved with the dynamic loading of an RSL file. It invokes the load client to load the module and then the load server remaps and links the library to the application. See the section on Real-time Shared Libraries for full details.