INtime SDK Help
Loading INtime Applications
INtime SDK v7 > Using INtime Software > Loading INtime Applications

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.

Loader components

There are three components involved with loading applications onto an INtime node.

Load server
A service within the INtime kernel which services load requests.
This service accepts requests to create new processes, allocate memory to those processes, load code and data into the memory and finally start the process.
Windows load client
A Windows application (ldrta.exe) which interacts with the load server to load a .RTA file and to create new process with it.
 
1. Windows load client (ldrta.exe) is invoked
2. The client reads the RTA file and communicates with the INtime load server via NTX
3. The server creates and starts the new process using the data received from the load client

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.

INtime load client
An INitme service which allows an INtime application to interact directly with the load server.
This client is used on INtime Distributed RTOS systems, where Windows is not present and the disk services are provided locally.
  
1. An existing INtime application calls CreateRtProcess to invoke the INtime kernel load client
2. The load client reads the RTA file and communicates with the load server
3. The load server creates and starts the new process using the data provided by the load client

Loader operation

The load process performs the following steps:

  1. Create a new, empty process
  2. Allocate memory to receive code and initialized data
  3. Load and link any referenced dynamic libraries
  4. Start the new process

The load client provides the following information to the load server to create a new process:

Using the INtime API

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.

In the current implementation the target node must be on the same host as the caller.

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.

Using the NTX API

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

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

Other considerations

There are a number of additional features built around the application loader to provide more product features:

Load server configuration

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.

Loader Synchronization

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.

Waiting for an application to exit and retrieve the exit code

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;
    RTHANDLE hProc, hWait;
    DWORD dwExitCode;

    // create the process with the PROC_SUSPEND flag in order to use the
    // StartRtProcess call

    dwFlags = PROC_SUSPEND;
    hProc = CreateRtProcess("c:\\dev\\myapp\\Debug\\myapp.rta", NULL, NULL, dwFlags);
    if (hProc == BAD_RTHANDLE) {
        printf_s("Failed to create process %04x\n", GetLastRtError());
        return 1;
    }

 

    // start the process and receive the wait handle
    hWait = StartRtProcess(hProc);

 

    // wait for the end of the process using the wait handle
    if (WaitForRtProcessEx(hWait, WAIT_FOREVER, &dwExitCode)) {
        printf_s("Process %04x has exited with exit code %d\n", hProc, dwExitCode);
    }
    else {
        printf_s("WaitForRtProcessEx has failed with status %04x\n", GetLastRtError());
    }

Synchronization with Windows services

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.

Automatically loading an application when the node starts

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 scripting

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.

Loading an INtime application from a binary resource

A Windows application may load a real-time application by calling ntxCreateRtProcess with the name of an RTA file. Alternatively, the RTA can be stored as a binary resource inside the Windows application itself and loaded with a call to ntxCreateRtProcessFromResource. The RTA is copied to a temporary file and loaded. Using this call the Windows .exe file and the associated .rta file can be kept as a single binary object.

Loading from an RTA resource
Copy Code

 // find the RTA resource
      if( ((hRsrc = FindResource(theApp.m_hInstance,
                  MAKEINTRESOURCE(IDR_RTAPP),
                  TEXT("RTAPP"))) == NULL) ||
            ((dwRtaSize = SizeofResource(theApp.m_hInstance,hRsrc)) == 0)||
            (((hRta = LoadResource(theApp.m_hInstance,hRsrc)) == NULL)))
      {
            tmp.LoadString(IDS_CANNOT_LOAD);
            MessageBox(tmp);
            return;
      }

      if ((lpRta = LockResource(hRta)) == NULL)
      {
            tmp.LoadString(IDS_CANNOT_LOAD);
            MessageBox(tmp);
            return;
      }
      // Create the temporary file.
      hRtaFile    = CreateFile(_T(“RTApp.TMP”),
                        GENERIC_READ | GENERIC_WRITE,
                        0, // no share
                        NULL, // security
                        CREATE_ALWAYS,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);
      If( hRtaFile == INVALID_HANDLE_VALUE)
      {
            tmp.LoadString(IDS_CANNOT_LOAD);
            MessageBox(tmp);
            return;
      }
      // Write the resource into the file
      WriteFile(hRtaFile, lpRta, dwRtaSize, &dummy, NULL);
      CloseHandle(hRtaFile);
      hRemoteApp = ntxCreateRtProcess(hNtx,TEXT(“RTApp.TMP”),(LPTSTR)(LPCTSTR)args,
            &procAttribs, NTX_PROC_SHOW_PROGRESS );

Load server tuning

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

Dynamically-loaded libraries

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.

See Also

Processes

NTX

System & Status

Shared Libraries