Real Time Systems: Notes |
Existing widely used operating systems, including Unix, MS Windows, and Linux, were not designed with hard real time requirements in mind. There does not appear to be any practical way to modify them to achieve hard real-time predictability. It would be very costly to develop an entire new operating system (including all device drivers) from scratch. RT Linux attempts to solve this problem by providing a very restricted set of capabilities for the hard real-time portion of an application. An application is expected to be partitioned into a small hard-real-time part, which runs in the kernel as one or more RTLinux threads, and the rest of the application, which runs as one or more ordinary Linux processes.
RTLinux attempts to provide a subset of the POSIX API. This is very restricted, though, and should not be confused with the normal Linux API (which it resembles). The big difference is that the RTLinux functions are implemented to be called from *inside* the kernel, and the ordinary Linux functions are implemented to be called from *outside* the kernel.
The FSM Labs RTLinux web site. This has lots of advertising for the commercial RTLinux products, links to several interesting papers on RTLinux, and (hidden several levels down) links to the free download site for the open-source version.
The FSM Labs "current papers" on RTLinux, at http://www.fsmlabs.com/articles/articles.html, including a short introduction on how to write simple RTLinux applications.
The FSM Labs archived papers on RT Linux, at http://www.fsmlabs.com/articles/archive/, including the original RTLinux white paper and a set of tutorial "slides" on RTLinux, and a paper on RTLinux presented at a Usenix conference.
My notes on how to install the open source version of RTLinux.
The examples that are provided with the open-source version of RTLinux.
The documentation provided with the open-source version of RTLinux. Beware: It may not be completely up to date with the code.
Allessandro Rubini & Jonathan Corbet<'s Linux Device Drivers, 2nd Edition available for reading on the Web, in PDF format at http://www.xml.com/ldd/chapter/book/. The first few chapters provide a good introduction to Linux kernel modules. The first part of the chapter on kernel debuggin is useful. Other useful parts for this course include the explanations of kernel memory allocation and message logging.
An interesting article on the RTLinux patent.
US Patent & Trademark Office on-line search URL for Yodaiken RT Linux patent.
module consists of four parts:
Module Size Used by Not tainted loop 12888 0 soundcore 7108 0 (autoclean) autofs 13700 0 (autoclean) (unused) 3c59x 31312 1 iptable_filter 2412 0 (autoclean) (unused) ip_tables 15864 1 [iptable_filter] mousedev 5688 0 (unused) keybdev 2976 0 (unused) hid 22404 0 (unused) input 6240 0 [mousedev keybdev hid] usb-ohci 22088 0 (unused) usbcore 80512 1 [hid usb-ohci] ext3 72960 3 jbd 56752 3 [ext3] raid1 16300 3
scripts/insrtl calls insmod to install them:
insmod modules/rtl.o insmod modules/rtl_time.o if [ -f modules/rtl_posixio.o ]; then insmod modules/rtl_posixio.o fi insmod modules/rtl_fifo.o insmod modules/rtl_sched.o if [ -f modules/psc.o ]; then insmod modules/psc.o fi
You should only need to use the modules rtl and rtl_sched for your work in this course.
See hello.c:
#include#include #include #include pthread_t thread; hrtime_t start_nanosec; void * start_routine(void *arg) { struct sched_param p; hrtime_t elapsed_time,now; p . sched_priority = 1; pthread_setschedparam (pthread_self(), SCHED_FIFO, &p); pthread_make_periodic_np (pthread_self(), gethrtime(), 500000000); while (1) { pthread_wait_np (); now = clock_gethrtime(CLOCK_REALTIME); elapsed_time = now - start_nanosec; rtl_printf("elapsed_time = %Ld\n",(long long)elapsed_time); } return 0; } int init_module(void) { start_nanosec = clock_gethrtime(CLOCK_REALTIME); return pthread_create (&thread, NULL, start_routine, 0); } void cleanup_module(void) { pthread_delete_np (thread); }
#define _XOPEN_SOURCE 600 #define _XOPEN_SOURCE_EXTENDED #define _POSIX_C_SOURCE 199506L #define _REENTRANT #include#include #include #include #include #include #define CHECK(CALL) if (CALL) { perror (#CALL); exit (-1); } #define SECOND_AS_NS 1000000000 #define HALF_SECOND_AS_NS 500000000 pthread_t thread; struct timespec start_time; pthread_mutex_t M; pthread_cond_t C; volatile int going = 1; void * start_routine(void *arg) { struct timespec now, wakeup_time; unsigned long elapsed_time; wakeup_time = start_time; while (going) { pthread_mutex_lock(&M); pthread_cond_timedwait (&C,&M,&wakeup_time); pthread_mutex_unlock(&M); if (clock_gettime(CLOCK_REALTIME, &now)) { perror ("clock_gettime"); break; }; elapsed_time = now.tv_sec - start_time.tv_sec; elapsed_time = elapsed_time * SECOND_AS_NS + (now.tv_nsec - start_time.tv_nsec); fprintf(stderr, "elapsed_time = %ld\n", elapsed_time); wakeup_time.tv_nsec += HALF_SECOND_AS_NS; if (wakeup_time.tv_nsec >= SECOND_AS_NS) { wakeup_time.tv_nsec -= SECOND_AS_NS; wakeup_time.tv_sec++; } } return 0; } int main () { pthread_attr_t attr; struct sched_param param; param.sched_priority = sched_get_priority_max(SCHED_FIFO); CHECK (pthread_attr_init (&attr)); CHECK (pthread_attr_setschedpolicy (&attr, SCHED_FIFO)); CHECK (pthread_attr_setschedparam (&attr, ¶m)); CHECK (clock_gettime (CLOCK_REALTIME, &start_time)); CHECK (pthread_mutex_init (&M, NULL)); CHECK (pthread_cond_init (&C, NULL)); CHECK (pthread_create (&thread, NULL, start_routine, 0)); fprintf(stderr, "hit the the enter-key to terminate\n"); getc(stdin); going = 0; CHECK (pthread_join (thread, NULL)); return 0; }
This is not RT Linux. It is just for comparison.
See program bisection.c.
Recall that we discussed the breakdown load or breakdown utilization of a system in the notes on measuring execution time.
Observe that this program needs synchronization between the main program, which drives the bisection by increasing and decreasing the load, and the periodic task. The basic idea is to run the periodic task for a while at a given load level, and see whether it misses any deadlines. Then, the load level is adjusted up or down and the periodic task is allowed to run some more. This starting and stopping of the periodic task is done using a POSIX condition variables and a POSIX mutex. They are also used at the beginning, to make the task wait for the main program to tell it to go, and at the end, to synchronize the shutdown of the periodic task.
RT Linux provides its own features that are supposed to behave like POSIX condition variables and mutexes.
See mutex.c.
We will walk through and discuss this in class.
See condvar.c.
We will walk through and discuss this in class.
© 1998, 2003 T. P. Baker.
No part of this publication may be reproduced, stored in a retrieval system, or
transmitted in any form or by any means without written permission.
$Id: rtlinux.html,v 1.1 2003/10/17 12:34:01 baker Exp baker $ |