Как реализовать потокобезопасный таймер на Linux? - PullRequest
4 голосов
/ 23 марта 2009

Как мы знаем, что-то делать в обработчиках сигналов очень плохо, потому что они работают в контексте, подобном прерыванию. Вполне возможно, что различные блокировки (включая блокировку кучи malloc ()!) Удерживаются при вызове обработчика сигнала.

Итак, я хочу реализовать потокобезопасный таймер без использования сигнального механизма.

Как мне это сделать?

Извините, на самом деле, я не ожидаю ответов о поточно-ориентированных, но о реализации таймера в Unix или Linux, который является поточно-ориентированным.

Ответы [ 4 ]

4 голосов
/ 23 марта 2009

Используйте usleep (3) или sleep (3) в вашей теме. Это заблокирует поток до истечения времени ожидания.

Если вам нужно подождать с вводом / выводом и истечь таймер до того, как какой-либо ввод / вывод будет готов, используйте select (2), poll (2) или epoll (7) с таймаутом.

Если вам все еще нужно использовать обработчик сигнала, создайте канал с pipe (2), выполните чтение блокировки на стороне чтения в вашей теме или используйте select / poll / epoll, чтобы дождаться его готовности, и записать байт в конец записи вашего канала в обработчике сигнала с помощью write (2). Неважно, что вы пишете в канал - идея состоит в том, чтобы просто проснуться. Если вы хотите мультиплексировать сигналы на одном канале, запишите номер канала или другой идентификатор в канал.

1 голос
/ 23 марта 2009

Я думаю, что обычный способ обойти описанные вами проблемы - заставить обработчики сигналов выполнять лишь минимальный объем работы. Например. установка некоторого флага timer_expired. Затем у вас есть поток, который регулярно проверяет, установлен ли флаг, и выполняет ли он реальную работу.

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

1 голос
/ 23 марта 2009

Возможно, вам следует использовать что-то вроде pthreads, библиотеку потоков POSIX. Он предоставляет не только сами потоки, но и базовые примитивы синхронизации, такие как мьютексы (блокировки), условия, семафоры. Вот учебник, который я нашел, который кажется приличным: http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

Для чего бы это ни стоило, если вы совершенно незнакомы с многопоточным программированием, вам может быть немного легче изучить его на Java или Python, если вы знаете какой-либо из них, чем на C.

0 голосов
/ 12 декабря 2013

Используйте интервальный таймер Posix и сделайте так, чтобы он уведомлял через сигнал. Внутри функции обработчика сигнала почти ни одна из функций C, таких как printf (), не может быть использована, поскольку они не являются входящими.

Используйте один глобальный флаг, объявленный статическим изменчивым для обработки вашим обработчиком сигнала. Обработчик должен буквально иметь эту одну строку кода, и НИЧЕГО другого; Этот флаг должен влиять на управление потоком в другом месте в потоке 1 & Only в программе.

static volatile bool g_zig_instead_of_zag_flg = false;
...
void signal_handler_fnc()
     g_zig_instead_of_zag_flg = true;
return

int main() {

   if(false == g_zig_instead_of_zag) {
      do_zag();
   }  else  {
      do_zig();
      g_zig_instead_of_zag = false;
    return 0;
}

Майкл Керриск Интерфейс программирования Linux содержит примеры обоих методов и еще несколько, но примеры содержат множество его собственных частных функций Вы должны начать работать, и примеры тщательно избегают многих ошибок, которые они должны исследовать, так что не очень.

Использование интервального таймера Poxix, который уведомляет через поток, делает все намного хуже, и AFAICT, этот метод уведомления в значительной степени бесполезен. Я только говорю, потому что я допускаю, что может быть НЕКОТОРЫЙ случай, когда ничего не делать в потоке main (), а все в потоке обработчика полезно, но я точно не могу вспомнить ни одного такого случая.

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