next up previous contents
Next: Creating Processes Up: Principles of Real-Time Operating Previous: Processes   Contents

What is wrong with Linux?

UNIX has the bad reputation of not being a real-time operating system. This needs some explanation. Time is an essential ingredient of a real-time system: the definition says that a real-time system must respond within a given time to an external stimulus. Theoretically, it is not possible to guarantee on a general UNIX time-sharing system that the response will occur within a specified time. Although in general the response will be available within a reasonable time, the load on the system cannot be predicted and unexpected delays may occur. It would be a bad idea to try and run a time-critical real-time application on an overloaded campus computer. Nevertheless, before discarding altogether the idea of using UNIX or Linux as the underlying operating system for a real-time application, we should have a critical look at what the requirements really are, to what extent they are satisfied by off-the-shelf Linux, and what can be done (or has been done already) to improve the situation.

The UNIX and Linux schedulers have been designed for time-sharing the CPU between a large number of users (or processes). It has been designed to give a fair share of the resources, in particular of CPU time, to all of these processes. The priorities of the various processes are therefore adjusted regularly in order to achieve this. For instance, the numerical analyst who runs CPU-intensive programs and does practically no I/O, will be penalized, to avoid that he absorbs all the CPU time.

Such a scheduling algorithm is not suitable for running a real-time application. If the operating system would decide that this particularly demanding application had consumed a sufficiently large portion of the available CPU time, it would lower its priority and the application might not be able anymore to meet its deadlines.

A real-time application must have high priority and -- in order to be able to meet its deadlines -- must run whenever there is no runnable program with a higher priority. In practice, the real-time process should have the highest priority, and it should keep this highest priority throughout its entire life9. Another scheduling algorithm is therefore required: a certain class of processes should be allocated permanently the highest priorities defined in the system. The normal scheduler of Linux did not have this feature, but another scheduler, designed for mixed time-sharing and real-time use is available and is usually compiled into the kernel.

Time being a precious resource for a real-time system, overheads imposed by the operating system should be avoided as much as possible. Some of the overheads can be avoided by careful design of the real-time program. For instance, knowing that forking a new process is a time-consuming business, all processes which the real-time application may need to run, should be forked and exec'ed (the fork and exec system calls will be illustrated in section 5) during the initialization phase of the application. Other overheads cannot be avoided so simply and need some adaptation or modification of the operating system.

Context switches may be very expensive in time, in particular when the code of the new process to be run is not yet available in memory and/or when room must be made in memory. All code and data of a real-time application should be locked into memory, so that this part of a context switch would not cause a loss of time. Locking everything into memory will also prevent page faults to happen, avoiding this way other memory swapping operations. Originally Linux did not have the possibility of locking processes into memory, but again, memory locking is now compiled into all recent kernels.

A further help in reducing the overheads due to context switches is to use so-called light-weight processes or multi-threaded user processes. Linux as such does not provide these, but library implementations do exist to implement the standard POSIX pthreads.

Other places where to watch for lurking losses of time are Input/Output operations. Normally, when a file is opened for writing, an initial block of disc sectors is allocated -- usually 4096 bytes -- and inodes and directory entries are updated. When the file grows beyond its allocated size, the relatively lengthy process of finding another free block of 4096 bytes and updating inodes and directory entries is repeated. A real-time system should be able to grab all the disc space it needs during initialization, so that these time losses may be avoided. Linux does not allow this at present.

All input and output in Linux is synchronous. This means that a process requesting an I/O operation will be blocked until the operation is complete (or an error is returned). Upon completion of the operation, the process becomes runnable again and it will effectively run when the scheduler decides so. However, ``completion'' of an output operation means only that the data have arrived in an output buffer, and there is no guarantee that the data have really been written out to tape or disc. When the process is only notified of completion of the I/O operation when the data are really in their final destination, we have synchronized I/O, which may be a necessity for certain real-time problems. Linux does not spontaneously do synchronized I/O, but it can be easily imposed by using sync or fsync.

Asynchronous I/O may be another real-time requirement. It means that the process requesting the I/O operation should not block and wait for completion, but continue processing immediately after making the I/O system call. The standard device drivers of Linux do not work asynchronously, but the primitive system calls allow the option of continuing processing. A special purpose device driver could make use of this and thus do asynchronous I/O. The process will then be notified with an interrupt when the I/O operation has been completed.

The designer of a real-time system should of course also be aware that no standard device drivers exist for exotic10 devices. They have to be written by the application programmer. In a standard UNIX system, such a new device driver must be compiled and linked into the kernel. Linux has a very nice feature: it allows to dynamically load and link to the kernel so-called modules, which can be -- and very often are -- device drivers.

We have shown before that it would be wise to divide a real-time system up into a set of processes, which can each care for their own business, without excessively interfering with each other. Nevertheless, some communication between processes may be needed. Old UNIX systems had only two interprocess communication mechanisms: pipes and signals. Signals have a very low information content, and only two user definable signals exist. System  V  UNIX added other IPC mechanisms: sets of counting semaphores, message queues, and shared memory. Most Linux kernels have the System  V IPC features compiled in.

Probably no real-time system could live without a real-time clock and interval timers. They do exist in off-the-shelf systems, but the resolution, usually 1/50  th or 1/100  th of a second, may not be enough. The user-threads package can work with higher resolutions, if the hardware is adequate.

The IEEE has made a large effort to standardize the user interface to operating systems. The result of this effort has been the POSIX 1003.1a standard, which defines a set of system calls, and POSIX 1003.1b, which defines a standard set of Shell commands. Both were approved by IEEE and by ISO and thus gained international acceptance. Also real-time extensions to operating systems have been defined in the POSIX 1003.1c-1994 standard, which has also been accepted by ISO. All the points discussed above are part of this POSIX 1003.1c standard, except for the multiple threads and mutexes, which are defined in a later extension. To the best of my knowledge, the so-called ``pthreads'' are now also an part of the international standard. Linux is POSIX 1003.1a and .1b compliant, although it may not have been officially certified.

In summary, Linux used to be weak on the following, and may still be on a few items:


next up previous contents
Next: Creating Processes Up: Principles of Real-Time Operating Previous: Processes   Contents
Catharinus Verkerk 2001-12-17