|
Прецизионный таймер в Linux, Нужен таймер менее 10mS |
|
|
|
Apr 6 2006, 08:39
|
Участник

Группа: Новичок
Сообщений: 32
Регистрация: 1-07-05
Пользователь №: 6 454

|
Добрый день. Подскажите как в Linux можно реализовать посылку сигнала SIGALRM в мое приложение с периодом порядка 100us(микросекунд).
Настройка обычного таймера в Linux согласно man предполагает минимальный период 10 ms.
Вариант с перекомпиляцией ядра для уменьшения времени отклика не подходит.
Какие еще могут быть способы реализовать таймер?
|
|
|
|
|
Apr 6 2006, 09:08
|
Участник

Группа: Свой
Сообщений: 22
Регистрация: 9-12-04
Пользователь №: 1 425

|
Думаю реализовать такой таймер средствами Linux не получится. Linux не является системой с жестким realtime, соответственно нет никакой гарантии, что в ядре нет функций выполняющихся дольше 100 мкс, и следовательно, оно не сможет гарантировать посылку сигнала. Единственный выход в таком случае использовать прерывание, генерируемое с требуемой частотой. Но если речь идет о платформе х86, то разрешения системного таймера вряд ли хватит. Т.е. только вариант прерывания с нужной частотой от внешнего устройства.
|
|
|
|
|
Apr 6 2006, 09:08
|

Гуру
     
Группа: Админы
Сообщений: 3 621
Регистрация: 18-10-04
Из: Москва
Пользователь №: 904

|
В ядре Линукса есть определение макроса HZ=100, который определяет частоту вызова шедулера при переключении задач. Т.е. задачи по умолчанию переключаются с частотой 100 Гц, иными словами, период переключения задачи = 10 мс, что и указано в man. Если хотите сделать задержки меньше, то можете попытаться организовать отдельный поток и вызывать в нем функцию usleep, которая может приостанавливать выполнение (давать задержку) на заданное число микросекунд.
--------------------
BR, Makc В недуге рождены, вскормлены тленом, подлежим распаду. (с) У.Фолкнер.
|
|
|
|
|
Apr 6 2006, 10:07
|
Группа: Новичок
Сообщений: 14
Регистрация: 3-02-06
Пользователь №: 13 960

|
Цитата(vzn @ Apr 6 2006, 12:39)  Добрый день. Подскажите как в Linux можно реализовать посылку сигнала SIGALRM в мое приложение с периодом порядка 100us(микросекунд).
Настройка обычного таймера в Linux согласно man предполагает минимальный период 10 ms.
Вариант с перекомпиляцией ядра для уменьшения времени отклика не подходит.
Какие еще могут быть способы реализовать таймер? Я одно время работал в QNX 6.x. Так там можно библиотечными функциями устанавливать требуемую частоту срабатывания аппаратоного таймера (до 10 мкс). И как написано в хелпе, ОС именно по прерыванию аппартного таймера вызыват шедулер, обрабатывает таймеры и т.д. То есть разрешение таймера POSIX не может быть меньше, чем частота работы аппартного таймера. Но на эту частоты можно повлиять. Поищите описание аппаратного таймера в Инете. Никто не мешает Вам реализовать программный псевдотаймер. То есть просто крутить циклы, которые делают какую нибудь пустую работу.
|
|
|
|
|
Apr 6 2006, 11:33
|
Местный
  
Группа: Свой
Сообщений: 351
Регистрация: 11-09-05
Из: Харьков
Пользователь №: 8 458

|
Цитата(vzn @ Apr 6 2006, 11:39)  Вариант с перекомпиляцией ядра для уменьшения времени отклика не подходит. Какие еще могут быть способы реализовать таймер? Если бы  ... ваш вариант гораздо хуже, чем просто перекомпиляция ядра  : - все службы времени ОС привязаны к системному тику (timeslice)... - это не совсем то же, что интервал (о чём говорили здесь: HZ=100) решедулирования (например в QNX6 интервал решедулирования = 4 * timeslice и изменить это никакими силами нельзя), но они могут и совпадать ... не помню что там в Linux...; - но если вы и уменьшите интервал до T, то, согласно требованиям POSIX 1003b (realtime расширения) - время срабатывания временных интервалов минимальное будет 3T ... с большой вероятностью  , иногда - 2T (это всё объясняется, но не место здесь это делать); - итого, вам нужно было бы уменьшить timeslice как минимум до 30мкс (в 300 раз)... - при этом решедулирование и всё обслуживание системного времени участиться в 300 раз ... и в разы завалит вам итоговую производительность системы... Цитата(makc @ Apr 6 2006, 12:08)  Если хотите сделать задержки меньше, то можете попытаться организовать отдельный поток и вызывать в нем функцию usleep, которая может приостанавливать выполнение (давать задержку) на заданное число микросекунд. Не поможет  - все события в системе, разделённые интервалом времени меньше timeslice - неразличимы и выглядят так, как если бы они произошли в одной точке времени. Чем делу можно помочь? Можете попробовать использовать другой задатчик времени: RTC (который на IRQ8 сидит а не на IRQ0) ... можете об этих делах почитать здесь: http://qnx.org.ru/index.php?option=com_min...273&page=0.htmlhttp://en.wikipedia.org/wiki/Real-time_clockА вот здесь: ftp://ftp.qnx.org.ru/pub/projects/ed1k/clock.tgz- лежит давненько уже написанная статья, одним знакомым, где с полным программным кодом показывается и объясняется как это делается... Только тягомутина всё это организовать - "ещё та"  , и есть смысл этим заниматься, только если действительно нужно и ничего другого придумать нельзя. P.S. но, кстати, использование любого внешнего аппаратного источника, как здесь предлагали, программно не будет проще, т.к. RTC и есть уже такой источник.
|
|
|
|
|
Apr 6 2006, 11:46
|
Местный
  
Группа: Свой
Сообщений: 351
Регистрация: 11-09-05
Из: Харьков
Пользователь №: 8 458

|
Цитата(vzn @ Apr 6 2006, 12:39)  Подскажите как в Linux можно реализовать посылку сигнала SIGALRM в мое приложение с периодом порядка 100us(микросекунд). На худой конец  - вы ведь не сказали что в этот период должно выполняться? - если это требуется что-то типа тайм-аут на блокирующей операции, то можно изобразить что-то по типу активного ожидания: Цитата(yanich @ Apr 6 2006, 13:07)  Никто не мешает Вам реализовать программный псевдотаймер. То есть просто крутить циклы, которые делают какую нибудь пустую работу. 1. запускаем отдельный поток приоритетом на 1 меньше - он тут же вытесняется... 2. запускаем блокирующую операцию, которую нужно ждать "не более чем"... 3. в состояние RUN переходит вытесненный поток... 4. который может "просто крутить циклы" ... но проще использовать функции активного ожидания POSIX (которые делают то же самое, только не нужно программные циклы в единицы времени пересчитывать на разных процессорах): см. nanospin(), spin() POSIX-овские, или что там есть (точно есть) их Linux эквиваленты... 5. как только активные циклы "накрутились" - поток посылает SIGALRM (или всё что угодно) блокированному родителю... 6. и тот разблокируется сигналом.
|
|
|
|
|
Apr 7 2006, 07:21
|
Местный
  
Группа: Свой
Сообщений: 351
Регистрация: 11-09-05
Из: Харьков
Пользователь №: 8 458

|
Цитата(Harbour @ Apr 6 2006, 22:08)  Попытки вытянуть за уши из non-rt реализации rt задачу ничем хорошим не закончится. Хотите без пыли и шуму получить надежный rt в userspace - юзайте rtai. Ну, наверное, не совсем так категорично: измените временнЫе масштабы (из микросекундного диаппазона в ... сотне миллисекундный  ) и траблы такого рода даже не будут возникать. А есть RT задачи, которые требуют вот этого RT качества в микросекундной шкале, а есть и такие - которые в секундной.
|
|
|
|
|
Apr 7 2006, 10:22
|
Участник

Группа: Новичок
Сообщений: 32
Регистрация: 1-07-05
Пользователь №: 6 454

|
Спасибо всем за дельные советы.
Пока я остановился на следующем решении основаном на использовании rdtscl()(#include <asm/msr.h>). Оно конечно не оптимальное, но для моих условий пока подходит.
Привязал исполнение моей real-time задачи не к SIGALRM, а к счетчику тактов процессора. То есть задача должна выполнятся например каждые 100us. Для этого оцениваем, сколько тактов нашего процессора в этих 100us. Часть тактов выполняем задачу (задача выполняется менее чем за 100us) часть тактов ждем ничего не делая, пока не на тикает оставшееся количество тактов. Все в обычном цикле.
При исполнении только моего приложения и ничего кроме него, решение дает приемлемый результат по точности. Если исполняется еще что-либо, то происходят сбои.
|
|
|
|
|
Apr 7 2006, 10:44
|
Местный
  
Группа: Свой
Сообщений: 351
Регистрация: 11-09-05
Из: Харьков
Пользователь №: 8 458

|
Цитата(vzn @ Apr 7 2006, 13:22)  Пока я остановился на следующем решении основаном на использовании rdtscl()(#include <asm/msr.h>). Оно конечно не оптимальное, но для моих условий пока подходит.
Привязал исполнение моей real-time задачи не к SIGALRM, а к счетчику тактов процессора. То есть задача должна выполнятся например каждые 100us. Для этого оцениваем, сколько тактов нашего процессора в этих 100us. Часть тактов выполняем задачу (задача выполняется менее чем за 100us) часть тактов ждем ничего не делая, пока не на тикает оставшееся количество тактов. Все в обычном цикле.
При исполнении только моего приложения и ничего кроме него, решение дает приемлемый результат по точности. Если исполняется еще что-либо, то происходят сбои. Вы то же самое могли бы сделать и по схеме с сигналами или любым другим асинхронным уведомлением (это и проще по коду, и точнее будет - затраты на вычисления уйдут из цикла активного ожидания): - запускаете пустой цикл с rdtscl() (это на самом деле 1 команда RDTSC на x86)... - и как только счётчик перевалит через заранее фиксированное значение - kill() самому себе ... SIGUSR1 или SIGRTMIN ... - а в обработчике сигнала - запуск своей кратковременной задачи. Или, если так больше нравится - всё то же можно выполнить в 2-х потоках. Цитата(Harbour @ Apr 7 2006, 11:53)  Есть такая фигня как гарантированный deadline - запутят на той non-rt оси какой-нить низкоприоритетный процесс, который заюзает ram+swap на 100% - и скажем bye-bye этому "realtim'у", пусть даже секундному и никакие posix расширения не спасут. В общем ... оно и правильно. Но свопирование во всех (нормальных  : FreeBSD, Linux) OS можно запретить для задачи - это обязательное условие для таких задач... так же как в QNX - оно всегда запрещено (или всегда отсутствует, если кому так больше нравитс  ). Но вопрос, заданный в этой теме - он не относится к какой-либо OS, он будет возникать везде... даже в уже "некуда далее RT"  QNX - можно уменьшить шаг системного времени до 10мксек (а минимальный интервал, как я уже говорил, вы принципиально не сделаете меньше 20мксек) - но всегда найдётся кто-то, кому понадобится временной шаг в ... 7 мксек  . И опять та же история: нельзя разрешить 2 события, временной интервал которых меньше шага системного времени ... независимо RT это OS или не RT.
|
|
|
|
|
Apr 7 2006, 11:45
|
Местный
  
Группа: Свой
Сообщений: 351
Регистрация: 11-09-05
Из: Харьков
Пользователь №: 8 458

|
Цитата(Harbour @ Apr 7 2006, 14:17)  В случае non-rt этого никто не гаранитурет - вот к примеру товарисч который померяет свой rtdsc вариант будет очень удивлен результатами, а если запустит ping -f, ls -lR /, xperf -all и т.д. то будет удручен  А он будет так же удручён, строя службу уведомления времени на RDTSC в любой ОС - это другая система времени, астрономическое время, отличное от службы системного времени ОС, и построенная на ней служба времени будет так же удручать, под какой самой RTOS её не построй (кстати, в этом крайне просто убеждаться: Linux-приложение перекомпилируется в QNX, из-за их общей gcc-основанности и ... убеждаемся, что всё так и есть). Но в его случае - это наипростейшее приемлемое (при некоторых условиях) решение.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|