Real-Time Linux and Its Application Programming Interface
In 2006, Linus Torvalds, the creator and maintainer of the Linux kernel, famously said of the idea of using the Linux kernel for real-time computing:
Controlling a laser with Linux is crazy, but everyone in this room is crazy in his own way. So if you want to use Linux to control an industrial welding laser, I have no problem with your using
PREEMPT_RT
. (Gleixner 2010)
The PREEMPT_RT
patch, the key to the
Real-Time Linux project (Foundation 2022), hardens the
real-time performance of the main Linux kernel, which was not developed
with real-time applications in mind. Since 2019, aspects of the PREEMPT_RT
patch have been accepted to the
Linux kernel (Foundation [2019] 2022). The
development of the project has been partly supported by industry
stakeholders such as ARM and National Instruments, the latter of which
uses it as the foundation of their NI Linux Real-Time operating system
used on many of their controllers, including our myRIO target.
The PREEMPT_RT
patch allows the
scheduler to preempt most, but not all, running tasks. Another approach
to using Linux as a real-time operating system is to create a small
real-time kernel and run Linux as a preemptable thread—see, for
instance, RTAI (R. Community
2022), RTLinux (Barabanov 2001; Divakaran
2002), and Xenomai (X. Community 2022). This approach, called
interrupt abstraction, makes it easier to
guarantee real-time performance but loses some of the advantages of
running Linux in the first place, because not all features of Linux are
available in these environments.
buttazzo2011, realtimelinux-basics, Reghenzani2019
The Real-Time Linux Application Programming Interface
Due to its conformity with the POSIX standards, the Real-Time Linux API for creating and managing real-time threads is available through the Linux C headers sched.h, time.h, and pthread.h.1 Functions for scheduling, threads, semaphores (including mutexes), real-time timers, and other real-time utilities are available.
Consider a simple program in which the main function creates a
thread. The thread can be started by calling the pthread_create()
function and providing it with a function to be run in the new thread.
The function then can terminate itself and its own thread by calling
pthread_exit()
. The
main function will wait for the thread to end when pthread_join()
is
called.
These functions are part of a standardized (IEEE) threading language in C called POSIX threads (pthreads). In our programs in lab 5, lab 6, lab 7, lab 8, we will use these functions in the following order.
pthread_create()
, for which the prototype is (Group 2018a),int pthread_create( *thread, // a pointer to the thread pthread_t const pthread_attr_t *attr, // running/scheduling parameters void *(*start_routine)(void*), // function to run in the thread void *arg); // argument for start_routine
is used to start the thread. This function prototype is in the pthread.h header, which also defines the thread type (
pthread_t
) and thread attribute type (pthread_attr_t
). The suppliedstart_routine()
function is executed at the start of the thread with argumentarg
. The thread attributesattr
can be used to set scheduling policies and parameters (e.g., priority). Ifattr == NULL
, the default attributes will be used.When the thread is no longer needed, a function within the pthread—for instance, the
start_routine()
function—can terminate the thread with thepthread_exit()
function (Group 2018b). This function’s prototype isvoid pthread_exit(void *value_ptr);
the only argument of which is a pointer
void *value_ptr
. The pointer allows information to be passed from the terminating thread to the thread that calledpthread_join()
, see below. Afterpthread_exit()
is called, thestart_routine()
function should end, stopping the thread.While this thread has been running, the main function that invoked
pthread_create()
has continued on in its original thread. At some point, before the end of the program, we should wait for the thread to end. This is usually done with thepthread_join()
function, for which the prototype isint pthread_join(pthread_t thread, void **value_ptr);
Here,
thread
is the same as that used inpthread_create()
, andvalue_ptr
is the pointer from thepthread_exit()
function.
The Real-Time Linux scheduler can be configured for task
deadlines (section 1.7, section 5.2) with the struct
sched_attr
and the function sched_setattr()
—see
realtimelinux-deadlines for more
information. Here, we have focused on managing real-time threads. There
are many more possibilities, some of which we will see as we
proceed.
ogness2020, Rybczynska2020, realtimelinux-howto, realtimelinux-deadlines
pthread_create
—Thread
Creation. IEEE Std 1003.1-2017. Open Group; IEEE. https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html#.
pthread_exit
—Thread Termination. IEEE
Std 1003.1-2017. Open Group; IEEE. https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_exit.html#.
See pthreadh,schedh,timeh.↩︎
Online Resources for Section 5.3
No online resources.