timer_create как остановить рекурсивный вызов функции потока после истечения первого таймера? - PullRequest
2 голосов
/ 01 апреля 2011

Я создал таймер с помощью простого «timer_create».Таймер создан с использованием SIGEV_THREAD.То есть, когда таймер истекает, происходит вызов функции потока таймера.

Как работает timer_create, предположим, предположим: expiry=3 сек и timer interval is 1 ns, тогда таймер продолжает тикать каждыедо истечения срока действия.Когда время таймера истекает, с этого момента он продолжает нажимать на функцию потока таймера через каждые 1 нс (интервал таймера).И продолжает создавать один поток за удар до тех пор, пока таймер не будет удален.

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

Как мне этого добиться?Можем ли мы поставить любую опцию в timer_create?Если нет другого API таймера?

Большое спасибо заранее

Ответы [ 2 ]

4 голосов
/ 01 апреля 2011

Я думаю, что это недостаток реализации в реализации glibc таймеров POSIX. Конечно, функция timer_getoverrun, которая критична для использования в реальном времени, не может работать в реализации glibc, так как она возвращает ядру счет переполнения для «текущего» истечения, но когда несколько событий истечения выполняются параллельно «текущий» не имеет смысла. Существуют также серьезные проблемы с истощением ресурсов и событиями истечения срока действия, которые делают реализацию непригодной для целей реального времени. Например, в nptl/sysdeps/unix/sysv/linux/timer_routines.c:

struct thread_start_data *td = malloc (sizeof (*td));

/* There is not much we can do if the allocation fails.  */
...

На справочной странице Linux для sigevent вы видите для SIGEV_THREAD:

К числу возможных вариантов реализации относится то, что каждое уведомление о таймере может привести к созданию нового потока или что один поток создается для получения всех уведомлений.

Последнее является единственным выбором, который может обеспечить правильную семантику в реальном времени, но по какой-то причине glibc не принял этот выбор.

Вот возможный обходной путь:

Выберите сигнал в реальном времени, заблокируйте этот сигнал перед созданием каких-либо потоков и настройте таймер на использование этого сигнала с SIGEV_SIGNAL. Теперь создайте поток для обработки вашего таймера (ов) и выполните цикл по sigwaitinfo, а затем вызывайте функцию-обработчик каждый раз, когда он возвращается. На самом деле это одна из возможных реализаций (и наиболее правильная) SIGEV_THREAD, которую должен использовать glibc .

Другая возможность: в POSIX есть ровно одна связанная с синхронизацией, не вызывающая syscall, безопасная асинхронно-сигнальная функция: sem_post. Таким образом, может быть возможно заставить обработчик сигнала (в отличие от получения сигнала от sigwaitinfo) синхронизироваться с другим потоком с целью доставки событий таймера. Но я не проработал детали, и кажется, что это все еще может быть трудно или невозможно.

1 голос
/ 02 апреля 2011

Просто установите интервал таймера на 0 и истекайте в любое время.Ваш таймер истечет один раз (и поток будет создан и запущен), а затем останется безоружным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...