2010-09-13 1 views
5

У меня есть асинхронная система потока данных, написанная на C++. В архитектуре потока данных приложение представляет собой набор экземпляров компонентов, которые инициализируются при запуске, затем они обмениваются данными с заранее определенными сообщениями. Существует компонент типа Pulsar, который предоставляет «сигнал синхросигнала» другим компонентам, которые подключаются к одному из них (например, Delay). Он запускает сообщение (вызывает API диспетчера потока данных) каждые X ms, где X - значение параметра «частота», которое задается в мс.Каков официальный способ вызова функции (C/C++) в ab. каждые 1/100 сек в Linux?

Короткий, задача состоит в том, чтобы вызвать функцию (метод) в каждом X ms. Вопрос в том, что это лучший/официальный способ сделать это? Есть ли какой-нибудь шаблон для этого?

Есть некоторые методы, которые я нашел:

  • Использование SIGALRM. Я думаю, сигнализация не подходит для этой цели. При этом разрешение составляет 1 секунду, это слишком редко.
  • Использование прерывания HW. Мне не нужна эта точность. Кроме того, я знаю, используя HW-решение (сервер скомпилирован для нескольких платформ, например ARM).
  • Измерьте прошедшее время и спящий() до следующего вызова. Я не уверен, что это лучший способ измерить время для вызова системных вызовов по времени на 5 потоков, каждый раз 10 раз в секунду - но, возможно, я ошибаюсь.
  • Использование функций ядра RealTime. Я ничего не знаю об этом. Кроме того, мне не нужен хрустальный точный вызов, это не атомный реактор, и я не могу установить RT-ядро на некоторых платформах (также доступно ядро ​​2.6.x).

Возможно, лучший ответ - это короткая часть исходного кода аудио/видео плеера (который я не могу найти/понять самостоятельно).

ОБНОВЛЕНИЕ (по просьбе @MSalters): Соавтор проекта DF использует Mac OSX, поэтому мы должны найти решение, которое работает на большинстве Posix-compilant op. систем, а не только на Linux. Возможно, в будущем появится целевое устройство, использующее BSD или ограниченный Linux.

+3

Сигнал подходит, несмотря на ваши оговорки. Проверьте «man setitimer», дайте ему понять и сообщите нам, если у вас есть актуальные проблемы. Если вы уже блокируете что-то вроде select(), вместо этого вы можете использовать значение тайм-аута. –

+0

Является ли сигнализация хорошим выбором для многопоточного приложения? Когда поступает сигнал, он должен быть «отправлен» в соответствующую нить. – ern0

+0

Сигнальные маски для потоковой передачи, поэтому вы можете блокировать 'SIGALRM' в каждом другом потоке. – caf

ответ

2

Чтобы быть честным, я считаю, что наличие «пульсара» в том, что, как утверждается, является асинхронной системой потоков данных, является недостатком дизайна. Либо он асинхронен, либо имеет синхронизирующее событие синхронизации.

Если у вас есть компонент, который нуждается в задержке, запросите его один, через boost::asio::deadline_timer.async_wait или любой из решений нижнего уровня (выберите()/epoll()/timer_create()/etc). В любом случае, наиболее эффективным решением для C++ является, вероятно, таймер boost.asio, поскольку они будут использовать то, что наиболее эффективно для вашей версии ядра Linux.

+0

Я не использую Boost и другие libs (только: stdlib, pthreads). Мы можем открыть аргумент в отношении дизайна; моя цель состояла в том, чтобы оставить Диспетчера (иногда также называемого брокер, планировщик) настолько слабым, насколько это возможно, поэтому Pulsar - это отдельный компонент. Возможно, в день Диспетчер предоставит функции/услуги таймера, но он будет подавать пульсары. Существуют и другие специальные функции Диспетчера, которые доступны через компоненты (например, порядок сообщений). Должен сказать, что моя система находится в состоянии «прототипа»: она работает, но есть что делать. – ern0

+2

Ну, что касается дизайна, я бы пошел с timer_create()/timer_settime(). Не забудьте поставить SIGEV_THREAD в sigev_notify для timer_create, чтобы он выдавал таймер на поток, а не обрабатывал. Это не было бы «официальным способом C++», но это было бы «официальным способом POSIX». – Cubbi

+0

Я не знал, что сигналы настолько дружелюбны, я попробую. – ern0

3

Если вам не нужны надежные гарантии в реальном времени, usleep должен выполнить эту работу. Если вам нужны жесткие гарантии в режиме реального времени, тогда потребуется функция на основе прерывания или реального времени.

+2

usleep устарел, вы должны использовать нанослоф ​​или выбрать – aeh

+0

Nanosleep - это круто, он сообщает оставшееся время при прерывании, но мне нужно вызвать функцию чтения времени, но каждый раунд, чтобы исправить количество спать, и я не хочу , – ern0

2

Альтернативой ранее упомянутым подходам является использование поддержки Timer FD в ядрах Linux 2.6.25+ (практически любое распределение, близкое к «текущему»). Timer FDs обеспечивают немного большую гибкость, чем предыдущие подходы.

+0

Да, это так здорово! Но я не хочу отказываться от BSD-совместимости (мой друг, который является соавтором в этом проекте, использует Mac, к сожалению). – ern0

+0

@ ern0: Пожалуйста, добавьте такие вопросы на вопрос! – MSalters

1

Пренебрегая вопрос дизайна (который я думаю, это интересный вопрос, но заслуживает свою собственную нить) ...

Я хотел бы начать с разработки идеи «прерывания», и с помощью сигналов или какую-то функцию ядра для прерывания каждого X usec. Я бы откладывал выполнение функций сна, пока другие идеи не были слишком болезненными.

Смежные вопросы