Getting Started with RTLinux

How important is scheduling?

This article deals with installing RTLinux, and creating a sample real-time module that can be loaded in it.

An operating system is responsible for managing, accessing, controlling and interacting with the computer hardware for general and special purposes. Most common PC operating systems (Windows, Macintosh, Linux and UNIX) are general-purpose operating systems (GPOS), but some tasks require special-purpose operating systems that provide specific services that are not available in GPOS. One such task is to obtain outputs from process execution in deterministic time frames. Such execution within a specific time bracket is known as real-time processing, for which you need a real-time operating system (RTOS).

In an RTOS, the basic idea is to assign the complete hardware resources to the application, and successfully execute it within a deterministic time. In GPOS, a process might be starved of CPU resources if a higher-priority process is scheduled. For example, your music file, playing in a media player, might be kicked off from the processor if the OS needs to service an interrupt. In GPOS, it’s hard to avoid random elements; execution doesn’t actually work on real-time deadlines.

RTOS take into consideration various mathematical formulas in order to execute the task; thus random elements in service availability, initialisation time and input parameters must be avoided, since they can seriously affect the real-time deadline of applications.

Many companies have worked on the development of different RTOS, including VxWorks, Windows CE, RTLinux and QNX. RTLinux (Real-Time Linux) is what I will be discussing in the course of this article, because it incorporates a beginner-friendly, fast and flexible architecture for providing hard real-time capabilities. RTLinux, developed by Wind River, is available in two variants:

  • Open RTLinux (under the GPL)
  • Wind River real-time core.

We will use Open RTLinux, with the freedom of the GPL (which is also free of cost). RTLinux has patches for both the 2.4 and 2.6 kernel series, but I would prefer the 2.4.x version, since it’s been extensively tested, and is almost free of bugs.

Let’s discuss the architecture of RTLinux. Figure 1 shows the traditional architecture of the general-purpose Linux system, where the kernel directly interacts with the hardware. All the interrupts are intercepted by the kernel itself.

GPOS Linux kernel

Figure 1: The GPOS Linux kernel

RTLinux system

Figure 2: RTLinux system

Figure 2 depicts the design of the RTLinux system. Three important aspects are displayed by the figure:

  • RTLinux sits between the real hardware and the kernel.
  • It acts as the hardware for the kernel.
  • It treats the kernel as a single big process.

The RT scheduler schedules the kernel on the processor. The priority of the kernel is lower compared to real-time tasks, and it can be pre-empted. All hardware interrupts are intercepted by the RTLinux layer, and if it’s not for an RT task, then the interrupt is passed to the Linux kernel as a software interrupt, when RTLinux is sitting idle.

Thus, two features are provided:

  • All RT tasks will get a real-time response whenever they need resources.
  • All non-RT tasks can be executed by the kernel when the RTLinux system is idle.

Configuring your system for RTLinux

Let’s now set about getting RTLinux running on a system. To test RTLinux, I have configured my system as follows:

  • Pentium 4 machine running CentOS 3 (Linux 2.4.21 as the base kernel).
  • ext2 for the root filesystem.
  • 2 GB of RAM

Prerequisites

Download the Linux kernel source, and the RTLinux patch. Here’s the link for my chosen kernel version, and rtlinux-3.2-wr.tar.bz2 from here.

Organise the source

Move these compressed files to the /usr/src directory and uncompress them (as root, but you already knew that!), as follows:

mv linux-2.4.21.tar.bz2 /usr/src
mv rtlinux-3.2-wr.tar.bz2 /usr/src
cd /usr/src
tar -jxvf  linux-2.4.21.tar.bz2
tar -jxvf  rtlinux-3.2-wr.tar.bz2

Let’s give these extracted directories shorter, easier-to-use aliases by creating soft links to them:

ln -s  linux-2.4.21  linux
ln -s rtlinux-3.2-wr  rtlinux

Patch it up

Apply the RTLinux patch to the vanilla kernel source, using the following steps:

cd linux
patch -p1 < ../rtlinux/patches/kernel-patch-2.4.21-rtl3.2-pre3

You may see this error during patching:

patch: **** malformed patch at line 1047: *+/

If so, then edit ./rtlinux/patches/kernel_patch-2.4.21-rtl3.2-pre3 in an editor. Go to line 1047 and change the following text:

(*+/
)

…to:

(+*/
)

Once again, extract the Linux source code (to revert to the original source) and then apply the modified patch, with the same commands given above.

Compile and install Linux

After the RTL patch is applied, proceed through the following steps to compile the kernel:

cd /usr/src/linux
make menuconfig

In the configuration menu, choose the exact processor type. You can find the name of the processor on your machine by running the cat /proc/cpuinfo command. Disable SMP support, and set the version information on all module symbols. Then proceed with the following code:

make dep
make modules
make modules_install
make install

Reboot your system. In the GRUB menu, you will find a new entry for the newly compiled kernel.

Compiling and installing RTLinux

Issue the following commands:

cd /usr/src/rtlinux
make menuconfig
make
make devices
make install

Post installation

After this, run the commands to check the status of the RTLinux modules. First of all, you should run the regression test:

./scripts/regression.sh

You should get [OK] for all the tests. If you get a [Failed], then it’s a fatal error; if you start RTLinux, it might crash the kernel. Something has gone wrong during the compilation and installation of the kernel.

If all tests return [OK], then run the following commands:

rtlinux status
rtlinux start

These will install all the modules present in the /usr/src/rtlinux/modules directory. Our own module will use only the symbols that are present in these modules.

Let’s get our hands dirty

Once RTLinux is set up, it’s ready to run a test module. To understand it better, there are a lot of examples provided along with the RTLinux patch, which you will find in the examples subdirectory. Let’s say “Hello” to RTLinux using the hello module.

  1. To compile, go to the examples directory, and execute the make command. The Makefile that should be already there will be used to create the object file.
  2. Now run the command insmod filename.o, where filename is the module name you want to load into the running kernel. For example, insmod hello.o.
  3. To view a list of loaded modules, use the lsmod command.
  4. To view the messages output by the newly loaded module, use the dmesg command.

A code fragment decoded

This program can be found in examples/hello. The aim of the module is to execute twice a second; during each execution, it will print the message “I’m here, my arg is 0″.

#include <rtl.h>
#include <time.h>
#include <pthread.h>
pthread_t thread;
void * start_routine(void *arg) {
    struct sched_param p;
    p.sched_priority = 1;
    pthread_setschedparam (pthread_self(), SCHED_FIFO, &p);
    pthread_make_periodic_np (pthread_self(), gethrtime(), 500000000);
    while (1) {
       pthread_wait_np();
       rtl_printf("I'm here; my arg is %x\n", (unsigned) arg);
    }
    return 0;
}
int init_module(void) {
     return pthread_create (&thread, NULL, start_routine, 0);
}
void cleanup_module(void) {
     pthread_cancel (thread);
     pthread_join (thread, NULL);
}

Now let me explain what each part of this code does.

  1. init_module() — The module is initialised using this function. It executes pthread_create to create a thread, and returns its success status. On successful execution of pthread_create, the start_routine function is called, with 0 as its argument.
  2. start_routine() — This comprises three components: initialisation, run-time and termination.

Initialisation

Executed when the code is run the first time after loading, the section of code written before the while loop tells the scheduler to assign this thread scheduling a priority of one, using p.sched_priority. It then sets the scheduler’s behaviour to be SCHED_FIFO for all subsequent executions, using pthread setschedparam. Finally, it calls the function pthread_make_periodic_np to run this thread after the given time period of 500 milliseconds.

Run-time

The block of code inside the while loop blocks all further execution of the thread using pthread_wait_np(). Once the thread is called again, after 500 milliseconds, it executes the rest of the code inside the while loop. However, since this is an infinite loop, with no exit condition, unless the module is unloaded using the rmmod command, it will keep executing the thread every 500 milliseconds.

Termination

The function *cleanup_module()* is called when the module is unloaded using rmmod command.

*# rmmod hello*

Then it calls pthread_cancel() to cancel the thread and pthread_join() to wait for the thread termination. This helps in freeing up any resources being used by the module.

  • Virendra Kumar

    Nice article

  • aashik

    How to then copy this created operating system to another system ?

  • Dave

    As indicated by the struck-out link, the RTlInuxFree site is down.
    I searched for the rtlinux-3.2-wr.tar.bz2 file, but only got a pointer to a dodgy-sounding Chinese site. Do you have (a) a good link for the file, or (b) a copy you could share?
    Regards & thanks

All published articles are released under Creative Commons Attribution-NonCommercial 3.0 Unported License, unless otherwise noted.
Open Source For You is powered by WordPress, which gladly sits on top of a CentOS-based LEMP stack.

Creative Commons License.