Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Программирование в режиме реального времениСтр 1 из 3Следующая ⇒
Программирование в режиме реального времени Модули 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().
Простейшая программа реального времени "Hello World" #include <rtl.h> #include <time.h> #include <pthread.h>
pthread_t thread;
void * start_routine (void * arg) { struct sched_param p; p. sched_priority = 1; pthread_setschedparam (pthread_self(), SCHED_FIFO, &p);
pthread_make_periodic_np (pthread_self(), gethrtime(), 500 000 000);
while (1) { pthread_wait_np (); rtl_printf("I'm here; my arg is %x\n", (unsigned) arg); } return 0; }
int init_module (void) { return pthread_create (&thread, NULL, start_routine, 0); }
void cleanup_module (void) { pthread_delete_np (thread); }
Записывайте эту программу в файл hello.c, копируйте любой файл rtl.mk из дистрибутива в ту же папку и компилируй программу вызовом команды: Make -f rtl.mk hello.o Замечание. Для успешной компиляции и инсталляции вы должны иметь Linux реального времени. Замечание. Эта программа может быть найдена в файле examples/hello.
Если на вашем компьютере загружены модули таймера (rtl_time.o) и планировщика (rtl_sched.o), то для запуска потоков вы можете использовать команду: Insmod hello.o Вы должны увидеть вывод сообщений потока. Для остановки программы выполните команду: Rmmod hello
Использование прерываний В Linux реального времени имеется два типа прерываний: аппаратные и программные. Программные прерывания являются нормальными прерываниями ядра Linux. Они имеют преимущество, что некоторые функции ядра Linux могут быть вызваны безопасно в процедурах обработки прерывания (некоторые из них зависят от версии ядра). Однако, во многих задачах они не обеспечивают жесткого исполнения в реальном времени, они могут задерживаться чем допустимое время задержки. Аппаратные прерывания (прерывания реального времени) имеют намного меньше задержку. Однако, как и потоки реального времени, они имеют ограниченный набор функций, которые могут быть вызваны в процедурах обработки прерываний. Решением этой проблемы является разделение функциональности между аппаратными и программными прерываниями.
#include <rtl_core.h>
int rtl_request_irq (unsigned int irq, unsigned int (*handler)(unsigned int, struct pt_regs *)); int rtl_free_irq (unsigned int irq);
Эти две функции используются для инсталляции и снятия процедур обработки аппаратных прерываний для определенных прерываний. Страницы руководства пользователя описывает эту работу в подробностях. Потоки реального времени вызываемые прерываниями могут быть созданы использованием функций запуска и остановки: int pthread_wakeup_np (pthread_t thread); int pthread_suspend_np (void); Поток управляемый прерыванием вызывает функцию pthread_suspend_np и блоков. Позже, процедура обработки прерывания вызывает функцию pthread_wakeup_np для этого потока. Поток будет запущен до тех пор, пока не выполнится следующий вызов функции pthread_wakeup_np.
Программные прерывания int rtl_get_soft_irq (void (*handler)(int, void *, struct pt_regs *), const char * devname); Эта функция размещает виртуальный номер прерывания и задает для него функцию как обработчик прерывания. Позже, это виртуальное прерывание будет запущен с помощью функции: void rtl_global_pend_irq(int ix); Эта функция безопасна при использовании в потоках реального времени и в прерываниях реального времени. Функция void free_irq(unsigned int irq, void *dev_id); является функцией ядра Linux, который снимает процедуру обработки прерывания для прерывания "irq". Для программных прерываний параметр dev_id должен быть равен 0. Программные прерывания использованы в реализации FIFO в Linux реального времени (файл fifos/rtl_fifo.c).
Написание планировщика и изменение стандартного планировщика Эта сложная тема должен записываться позже. Здесь только некоторые точки для отталкивания: Планировщик реализован в файле: scheduler/rtl_sched.c и в файлах зависимых от архитектуры (папки include/arch-i386 и scheduler/i386). Решение функциональности планировщика определена в функции rtl_schedule(). Путем изменения этой функции можно изменить политику планирования. Программирование в режиме реального времени Модули Linux Эта версия Linux реального времени поддерживает загрузку программ реального времени в виде модулей Linux. Исходный файл модуля Linux является обычным С файлом, в котором функция main() заменен парой функций init/cleanup: int init_module(); Эта функция вызывается, когда модуль загружается в ядро. Она должна вернуть 0, а в случае ошибки отрицательное число. void cleanup_module(); Эта функция вызывается, когда модуль разгружается. Компилированный модуль загружается в ядро с помощью команды insmod(1).
|
|||||||
Последнее изменение этой страницы: 2017-02-07; просмотров: 220; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.216.190.167 (0.025 с.) |