- Radboud University Nijmegen
- Exercise #1: The Basics of Real-Time Linux
- Real-Time Linux Introduction
- Objectives
- How does RT Linux work?
- How is the real-time kernel given higher priority than Linux kernel?
- RT Linux Tasks are not Linux Programs
- Xenomai
- Xenomai API
- C is the Preferred Language
- Creating a task
- Starting a task
- Hello World
- Linux в режиме реального времени
- Планировщик ЦП в реальном времени
- Планировщик с учетом приоритетности процессов
- Установка и использование RHEL Real Time
- Настройка и тестирование
- Использованные материалы
Radboud University Nijmegen
Exercise #1: The Basics of Real-Time Linux
Real-Time Linux Introduction
Linux is a free Unix-like operating system that runs on a variety of platforms, including PCs. Numerous Linux distributions such as Red Hat, Debian and Mandrake bundle the Linux OS with tools, productivity software, games, etc.
- The Linux scheduler, like that of other OSes such as Windows or MacOS , is designed for best average response, so it feels fast and interactive even when running many programs.
- However, it doesn’t guarantee that any particular task will always run by a given deadline. A task may be suspended for an arbitrarily long time, for example while a Linux device driver services a disk interrupt.
- Scheduling guarantees are offered by real-time operating systems ( RTOSes ), such as QNX, LynxOS or VxWorks . RTOSes are typically used for control or communications applications, not for general purpose computing.
- Linux has been adapted for real-time support. These adaptations are termed «Real-Time Linux» (RT Linux).
- Numerous versions of RT Linux are available, free or commercial. Three commonly available free RT Linux versions are
- RTLinux , developed by New Mexico Tech and now maintained by Wind River Systems.
- RTAI, The Real-Time Application Interface (RTAI), developed by the Milan Polytechnical University and available at https://www.rtai.org/.
- Xenomai , a spin off of RTAI Linux. While RTAI is focused on lowest technically feasible latencies, Xenomai also considers clean extensibility (RTOS skins), portability, and maintainability as very important goals. It is available at www.xenomai.org .
- These RT Linux systems are patches to the basic Linux kernel source code. Instructions for building an RT Linux system from a the Linux source code are provided with these RT Linux systems. Briefly, this involves setting up the basic Linux system, getting the latest Linux kernel source code from www.kernel.org, patching the kernel source code, and compiling the patched kernel.
Objectives
The following are the primary objectives of this exercise:
- To learn how Xenomai real-time Linux works and to build a small Xenomai real-time task.
How does RT Linux work?
The general idea of RT Linux is that a small real-time kernel runs beneath Linux, meaning that the real-time kernel has a higher priority than the Linux kernel. Real-time tasks are executed by the real-time kernel, and normal Linux programs are allowed to run when no real-time tasks have to be executed. Linux can be considered as the idle task of the real-time scheduler. When this idle task runs, it executes its own scheduler and schedules the normal Linux processes. Since the real-time kernel has a higher priority, a normal Linux process is preempted when a real-time task becomes ready to run and the real-time task is executed immediately.
How is the real-time kernel given higher priority than Linux kernel?
Basically, an operating system is driven by interrupts, which can be considered as the heartbeats of a computer:
- All programs running in an OS are scheduled by a scheduler which is driven by timer interrupts of a clock to reschedule at certain times.
- An executing program can block or voluntary give up the CPU in which case the scheduler is informed by means of a software interrupt (system call).
- Hardware can generate interrupts to interrupt the normal scheduled work of the OS for fast handling of hardware.
RT Linux uses the flow of interrupts to give the real-time kernel a higher priority than the Linux kernel:
- When an interrupt arrives, it is first given to the real-time kernel, and not to the Linux kernel. But interrupts are stored to give them later to Linux when the real-time kernel is done.
- As first in row, the real-time kernel can run its real-time tasks driven by these interrupts.
- Only when the real-time kernel is not running anything, the interrupts which were stored are passed on to the Linux kernel.
- As second in row, Linux can schedule its own processes driven by these interrupt.
Hence, when a normal Linux program runs and a new interrupt arrives:
- it is first handled by an interrupt handler set by the real-time kernel;
- the code in the interrupt handler awakes a real-time task;
- immediately after the interrupt handler, the real-time scheduler is called ;
- the real-time scheduler observes that another real-time task is ready to run, so it puts the Linux kernel to sleep, and awakes the real-time task.
- Hence, to the real-time kernel and Linux kernel coexist on a single machine a special way of passing of the interrupts between real-time kernel and the Linux kernel is needed. Each flavor of RT Linux does this is in its own way. Xenomai uses an interrupt pipeline from the Adeos project. For more information, see also Life with Adeos .
RT Linux Tasks are not Linux Programs
- In real-time Linux we can make a real-time program by programming real-time threads. None-real-time programs in real-time Linux just use the conventional Linux threads.
- A real-time task can be executed in kernel space using a kernel module, but it can also be executed in user space using a normal C program.
- Running in user space instead of in kernel space gives a little extra overhead, but with the following advantages :
- A bug in a kernel module can crash the whole system, however a bug in a user space program can only crash the program.
- In a kernel model one can only use the real-time API and the limited kernel API , but in a real-time user space program the real-time API and the whole Linux API can be used! However when using the Linux API in user space, the program cannot be scheduled by the real-time scheduler (HARD real-time) but must be scheduled by the Linux scheduler ( SOFT real-time). So calling a Linux API call from a real-time user space task will degrade its performance from HARD to SOFT real-time. After the call the task will return to the real-time scheduler.
Xenomai
- The Xenomai project was launched in August 2001.
- Xenomai is based on an abstract RTOS core, usable for building any kind of real-time interfaces, over a nucleus which exports a set of generic RTOS services. Any number of RTOS personalities called “skins” can then be built over the nucleus, providing their own specific interface to the applications, by using the services of a single generic core to implement it.
- The following skins on the generic core are implemented :
- POSIX
- pSOS +
- VxWorks
- VRTX
- native: the Xenomai skin
- uITRON
- RTAI: only in kernel threads
- Xenomai allows to run real-time threads either strictly in kernel space, or within the address space of a Linux process. A real-time task in user space still has the benefit of memory protection, but is scheduled by Xenomai directly, and no longer by the Linux kernel. The worst case scheduling latency of such kind of task is always near to the hardware limits and predictable, since Xenomai is not bound to synchronizing with the Linux kernel activity in such a context, and can preempt any regular Linux activity with no delay. Hence, he preferred execution environment for Xenomai applications is user space context.
- But there might be a few cases where running some of the real-time code embodied into kernel modules is required, especially with legacy systems or very low-end platforms with under-performing MMU hardware. For this reason, Xenomai’s native API provides the same set of real-time services in a seamless manner to applications, regardless of their execution space. Additionally, some applications may need real-time activities in both spaces to cooperate, therefore special care has been taken to allow the latter to work on the exact same set of API objects.
- In our terminology, the terms «thread» and «task» have the same meaning. When talking about a Xenomai task we refer to real-time task in user space, i.e., within the address space of a Linux process, not to be confused with regular Linux task/thread.
Xenomai API
- In our exercise we will use the native Xenomai skin and run real-time tasks in user space because working with them is easier and still HARD real-time.
- The Native Xenomai API is flexible and well documented.
- The most important characteristics of the Xenomai API are :
- Context independence
Xenomai’s native API provides the same set of real-time services in a seamless manner to application regardless of their execution mode is user or kernel mode.
Xenomai objects ( eg . a semaphore, task, etc ..) are always reachable even when the location of the object is another execution space than were the task using it is running. e.g . user space task running in user space can use a semaphore which is stored in kernel space.
To this end, each category of services in Xenomai’s native API defines a uniform descriptor type to represent the objects it manages. For instance, a task will always be represented by a RT_TASK descriptor, a message queue by a RT_QUEUE descriptor, and a semaphore by a RT_ SEM descriptor, regardless of the execution space from which they are used.
Xenomai uses a unified registry, to index each object descriptor under a symbolic name given by the user. By doing this, Xenomai enables you to retrieve any descriptor associated with a registered object in any location of your application.
- See Native API Tour for more information about Xenomai’s native API.
C is the Preferred Language
- Linux is written in the C programming language (with some assembly language), as is Xenomai , so C is the preferred language for writing RT Linux programs.
- Other languages (e.g., C++) can be used. For instance, see the Xeno — project which is providing a thin object-oriented software interface to Xenomai’s C-based skins.
- The examples in this tutorial are all written in C.
- C programs are normally compiled into full executable programs
- In C, a program’s «entry point» where execution begins is a function called ‘main( )’.
- Each real-time task is associated with a C function that is called when the task is scheduled to run.
Creating a task
- When you create a real-time task in Xenomai the RT_TASK structure is used as the descriptor to refer to this task.
- An RT_TASK data structure is used to hold all the information about a task:
- the task function to be executed by the real-time task,
- any initial argument passed to it,
- the size of the stack allocated for its variables,
- its priority,
- whether or not it uses floating-point math,
- and a «signal handler» that will be called when the task becomes active.
- The task is created by calling
- ‘ task ‘ is a pointer to an RT_TASK type structure which must have been declared before and whose structure is filled.
- ‘ name ‘ is an ASCII string standing for the symbolic name of the task. This symbolic name you can use to retrieve the task structure anywhere else in your code by calling the rt_task_ bind ( ) function.
- ‘ stack_size ‘ is the size of the stack to be used by the new task.
- ‘ priority ‘ is the priority to be given the task. The highest priority is 99, while the lowest is 1.
- ‘mode’ is a set of flags which affect the task :
- T_ FPU allows the task to use the FPU (Floating Point Unit) whenever available on the platform. This flag is forced for user-space tasks.
- T_SUSP causes the task to start in suspended mode. In such a case, the thread will have to be explicitly resumed using the rt_task_ resume ( ) service for its execution to actually begin.
- T_ CPU( cpuid ) specifies that the new task runs on the CPU with number cpuid . CPU identifiers range from 0 to RTHAL_NR_CPUS — 1 (inclusive).
- T_JOINABLE (user-space only) allows another task to wait on the termination of the new task. This implies that rt_task_ join ( ) is actually called for this task to clean up any user-space located resources after its termination.
Starting a task
- A task can be started by calling :
- ‘ task ‘ is a pointer to an RT_TASK type structure which must be already initialized by a call to rt_task_create().
- ‘ task_function ‘ is the the task function to be executed by this real-time task.
- ‘ arg ‘ is the void pointer argument given to the task function.
If you did specify T_SUSP as a mode flag to rt_task_ create( ), the task will be started in a suspended mode. In that case you have to explicitly resume the task with rt_task_resume (). Otherwise, the real time task is ready to execute immediately.
Hello World
The following «ex01.c» C code illustrates the creating and start of a «demo» task which writes a message.
Источник
Linux в режиме реального времени
Операционная система реального времени необходима, когда к работе процессора или потоку данных предъявляются жесткие временные требования. Таким образом она часто выполняет роль блока управления в специальных устройствах. Проведение научных экспериментов, приложения визуализации в медицине, промышленные устройства управления являются системами реального времени. Механизмы впрыска топлива автомобильных двигателей, контроллеры бытовой и военной техники также являются системами реального времени.
При этом разные события имеют различные временные требования. Например, требование к задержке для антиблокировочной тормозной системы может составлять от 3-5 миллисекунд. То есть с момента, когда колесо впервые обнаруживает, что оно скользит, у системы, управляющей антиблокировочными тормозами, есть от 3-5 миллисекунд, чтобы отреагировать и исправить ситуацию.
Возможности ядра в реальном времени существует уже более десяти лет в экосистеме программ с открытым исходным кодом. Столько же времени доступна поддержка Red Hat Enterprise Linux (RHEL) для ядра реального времени. Тем не менее многие системные администраторы неверно истолковывают его основные концепции и фактическое рабочее поведение. В этой статье я опишу некоторые из его основных функций, отличия от стандартного ядра и шаги по установке.
Планировщик ЦП в реальном времени
Для разных классов задач можно обозначить системы мягкого реального времени и системы жесткого реального времени. Первые не гарантируют точное время, когда критический процесс будет запланирован в реальном времени. Они гарантируют только то, что процессу будет отдано предпочтение перед некритическими процессами. Вторые имеют более строгие требования и задание либо выполняется в заданных временных рамках, либо считается не выполненным.
Мы называем задержкой события время, которое проходит с момента возникновения события до момента его обслуживания. Есть два типа задержек, оказывающих влияние на производительность ОС реального времени.
- Задержка прерывания относится к периоду времени от поступления прерывания в CPU до запуска процедуры обработки. Когда происходит событие, ОС должна сначала завершить выполняемую инструкцию и определить тип возникшего прерывания. Затем она должна сохранить состояние текущего процесса до обработки прерывания с помощью специальной процедуры, interrupt service routine (ISR).
Рис. 1 Задержка прерывания.
Время, необходимое диспетчеру планирования для остановки одного процесса и запуска другого, называется задержкой диспетчеризации. Предоставление задач реального времени с немедленным доступом к процессору требует, чтобы ОС реального времени минимизировали также и эту задержку. Наиболее эффективным методом поддержания низкой задержки отправки является предоставление ядер с приоритетным прерыванием.
Рис. 2 Задержка диспетчеризации.
Планировщик с учетом приоритетности процессов
Наиболее важной особенностью ОС реального времени — немедленно реагировать на критический процесс, требующий доступ к ресурсам CPU. В результате планировщик для операционной системы реального времени должен поддерживать алгоритм приоритетного прерывания. Такие алгоритмы назначают каждому процессу приоритет в зависимости от его степени важности. Если планировщик также поддерживает приоритетное прерывание, текущий процесс на CPU по запросу будет вытеснен в пользу более приоритетного процесса.
Рис. 3 Классификация планировщиков.
Существует несколько алгоритмов для планировщика в реальном времени.
- Rate-Monotonic Scheduling — алгоритм со статическим приоритетом класса планирования. Статические приоритеты назначаются в соответствии с продолжительностью цикла задачи, вследствие чего более короткие циклы имеют более высокий приоритет исполнения. В худшем случае КПД загрузки центрального процессора ограничен следующей величиной.
При числе процессов n, стремящемся к бесконечности ряд будет сходиться к ln2 ≈ 0.693147.
Earliest-deadline-first (EDF) Scheduling динамически назначает приоритеты в соответствии с крайним сроком. Чем раньше крайний срок, тем выше приоритет и чем позже крайний срок, тем ниже приоритет. В отличие от RMS, планировщик EDF не требует, чтобы процессы были периодическими и постоянно запрашивали одно и то же количество процессорного времени на пакет. Единственное требование состоит в том, чтобы процесс объявлял свой крайний срок планировщику, когда он готов к запуску.
Рис. 4 Планировщик EDF.
На рисунке видим общий принцип работы планировщика. На точке 4 был замещён T1 и его место занял T2 так как его крайний срок наступал раньше, чем у T2. После отработки T3 планировщик вернулся к T1, который завершился на отметке 23.
POSIX real-time-scheduling. Стандарт POSIX.4 определяет три политики планирования. Каждый процесс имеет атрибут планирования, который может быть выставлен в одну из трех вариантов политики.
- SCHED_FIFO — политика упреждающего планирования с постоянным приоритетом, при которой процессы с одинаковым приоритетом обрабатываются в порядке «первым пришел — первым обслужен» (FIFO). Данная политика может иметь не менее 32 уровней приоритета.
- SCHED_RR — политика аналогична SCHED_FIFO, но использует метод временного среза (циклический перебор) для планирования процессов с одинаковыми приоритетами. Он также имеет 32 уровня приоритета.
- SCHED_OTHER — политика не определена и зависит от системы; может вести себя по-разному в разных реализациях.
Установка и использование RHEL Real Time
Для начала следует подключить репозиторий Red Hat Enterprise Linux для Real Time, и установить группу пакетов RT.
В составе RT идут эти компоненты:
- kernel-rt — ядро с функционалом реального времени;
- rt-setup — установка окружения Red Hat Enterprise Linux Real Time;
- rt-tests — утилиты тестирования функций RT;
- rt-eval — для оценки возможности применять RT на данной системе;
После установки RT и перезагрузки нужно убедиться, что загружено ядро kernel-rt.
Посмотрим на некоторые отличия kernel-rt от стандартного ядра.
- При высокой нагрузке происходит проверка приоритета задачи (1-99).
- Высокоприоритетным (99) задачам отдается предпочтение при доступе к ресурсам центрального процессора.
- Не задействует политику Completely Fair Scheduling (CFS).
- Использует политику SCHED_FIFO, либо же SCHED_RR.
Рис. 5 Сравнение kernet_rt со стандартным ядром.
На графике показан замер времени отклика из миллиона повторений для систем, использующих ядра RHEL Linux 7 и RHEL Real Time соответственно. Синие точки на этом графике представляют время отклика (в микросекундах) систем со стандартным ядром RHEL 7, а зеленые — RHEL 7 Real Time. Из графика видно, что особенность kernel-rt в гораздо меньшей дисперсии и, соответственно, в большей предсказуемости времени отклика системы.
Настройка и тестирование
После установки RT может потребоваться дополнительная настройка и доводка для достижения наиболее стабильных показателей времени отклика системы. Такие требования могут предъявить компании финансового, или телекоммуникационного сектора. Сама настройка — итеративный процесс и нужно запастись терпением в начале процесса. Вряд ли получится подкрутить пару переменных и понять, что достигнут наилучший результат из возможных.
Утилита hwlatdetect из пакета rt-tests покажет задержки, вызванные аппаратным и микропрограммным обеспечением, путем опроса источника тактовых импульсов и поиска непонятных пропусков.
В данном примере parameters указывает на задержку и способ обнаружения. Порог задержки по умолчанию был выставлен на 10 микросекунд (10 μs).
RT имеет также утилиту rteval для тестирования производительности системы в реальном времени под нагрузкой. Программа создаёт большую нагрузку на систему, используя планировщик SCHED_OTHER, а затем измеряет отклик в реальном времени на каждом из активных CPU. Цель в том, чтобы постоянно выполнялись различные задачи, такие как выделение / освобождение памяти, дисковый I/O, вычисления, копирование памяти и другие.
Каждый поток измерений берет временную метку, бездействует в течение некоторого интервала, а затем принимает другую временную метку после пробуждения. Задержка по результатам измерения равна t1 — (t0 + i) , где
- t1 — фактическое время измерения;
- t0 — теоретическое время пробуждения первой временной метки;
- i — интервал ожидания.
Отчет утилиты rteval выглядит так.
Использованные материалы
- Abraham Silberschatz, Peter Baer Galvin, Greg Gagne Operating System Concepts 9-th edition.
- What are the benefits of running the Red Hat Enterprise Linux for Real Time?
- Working with the real-time kernel for Red Hat Enterprise Linux
- Advanced tuning procedures to optimize latency in RHEL for Real Time
Источник