
Программирование в режиме реального времени
Модули Linux
Эта версия Linux реального времени поддерживает загрузку программ реального времени в виде модулей Linux. Исходный файл модуля Linux является обычным С файлом, в котором функция main() заменен парой функций init/cleanup:
int init_module();
Эта функция вызывается, когда модуль загружается в ядро. Она должна вернуть 0, а в случае ошибки отрицательное число.
void cleanup_module();
Эта функция вызывается, когда модуль разгружается.
Компилированный модуль загружается в ядро с помощью команды insmod(1).
Написание потоков реального времени Linux
Потоки являются легкими процессами, которые разделяют адресное пространство ядра. В принципе поток управления ядром Linux RT (один для CPU), также является потоком Linux RT.
В Linux RT, все потоки разделяют адресное пространство ядра Linux. Для создания потока используйте функцию:
#include <pthread.h>
int pthread_create(pthread_t * thread,
pthread_attr_t * attr,
void * (*start_routine)(void *),
void * arg);
Замечание. Эта функция должна быть вызвана только из потока ядра Linux (например, в функции init_module()).
Поток создается путем использования объекта атрибута в параметре "attr". Если этот параметр равен NULL, то используются атрибуты по умолчанию. Посмотри также функций POSIX:
pthread_attr_init(3), pthread_attr_setschedparam(3),
pthread_attr_getschedparam(3),
и функций относящихся к RTL.
pthread_attr_getcpu_np(3), pthread_attr_setcpu_np(3)
ID созданного потока сохраняется в параметре "thread". Параметр start_routine является указателем на функцию, который определяет код потока. Параметр “arg” определяет параметров функции.
Чтобы удалить поток должна быть использована RTL-функция:
int pthread_delete_np (pthread_t thread);
Поток перестает работать немедленно.
Планировщик потоков
RTL определяет способ выполнения кода потока в определенные моменты времени (расписание). Linux реального времени имеет несколько таймеров, которые могут быть использованы для ведения расписания выполнения потоков. Чтобы заметить очередное чтение времени используйте функцию:
int clock_gettime(clockid_t clock_id, struct timespec *ts);
Параметр clock_id является идентификатором таймера.
Параметр ts - место для сохранения считанного значения.
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec /* nanoseconds */
};
Замечание. Текущие поддерживаемый таймер:
- CLOCK_UST (Unadjusted System Time). Этот таймер никогда не регулируется и не обнуляется. Этот таймер является очень чувствительным таймером.
- CLOCK_REALTIME. Стандартный таймер реального времени POSIX. В текущем состоянии этот таймер такой же, что и CLOCK_UST. Было запланировано, что этот таймер будет считать мировое время в будущих версиях RTL.
CLOCK_8254. Используется для ведения расписания в не SMP-машинах.
CLOCK_APIC. Используется в SMP-машинах. Показание этого таймера соответствует на показания таймера APIC процессора, который выполняет функцию clock_gettime. Вы не можете считывать и установить APIC-таймер других процессоров.
С помощью функции rtl_getschedclock(3) вы можете выбрать таймер, которого использует планировщик для ведения расписания
Linux реального времени использует планировщик управляемый приоритетами.
В этом планировщике, поток с наибольшим приоритетом будет выполняться первым. Если два потока имеют одинаковый приоритет, то который из них будет выбран не известен. Приоритет потока может быть изменен во время создания потока с помощью функции pthread_attr_setschedparam(3)или потом с помощью функции:
int pthread_setschedparam(pthread_t thread, int policy,
const struct sched_param *param);
Параметр policy в этих версиях RTL не используется, но должен быть определен как SCHED_FIFO для совместимости с будущими версиями.
Структура sched_param содержит объект параметра потока. Большие значения соответствуют к большему приоритету. Используйте функций
sched_get_priority_max(3) и sched_get_priority_min(3)
для определения возможных значений приоритета.
Чтобы поток реального времени выполнялся периодически используйте следующую функцию:
int pthread_setperiod_np(pthread_t thread,
const struct itimerspec *its);
struct itimerspec {
struct timespec it_interval; /* Период таймера */
struct timespec it_value; /* пределы таймера */
};
Эта функция отмечает поток как периодическим. Параметр “its” определяет время вызова потока: Поле it_value определяет время первого обращения;
Поле it_interval определяет время периода потока. Период может быть 0, который соответствует одноразовому вызову потока.
Действующее время выполнения таймера может быть получен:
int pthread_wait_np(void);
Эта функция останавливает выполнения вызова потока, до тех пор не достигнута время определенное в функции pthread_setperiod_np().