2013-11-25 3 views
1

Я пишу код на ucLinux для связи сокетов. Я использую select() для чтения данных о сокетах. У меня также есть таймер 20 мс (созданный с использованием setitimer), работающий в том же потоке для выполнения параллельной операции. Моя функция выбора блокируется каждый раз, когда «прерывается системным вызовом», так как он получает сигнал SIGALRM по таймеру при переполнении каждые 20 мс. Я попытался перезапустить систему, когда выпущен EINTR, и снова запустите select(). но это не поможет, так как я всегда получаю SIGALRM таймером каждые 20 мс. Я не хочу игнорировать этот сигнал, так как он используется для выполнения других задач в системе, но я хочу использовать select без влияния этого сигнала. Есть ли способ справиться с этим? Я не могу использовать такие функции, как timer_create(), поскольку они не поддерживаются на используемой платформе. Итак, я застрял с использованием setitimer для создания таймера. Есть ли способ, которым я могу работать независимо друг от друга в своем коде?Запуск сокета select() и таймеров в том же потоке linux

ответ

1

Возможно ли вам сделать что-то подобное?

While(1) { 
    int rc = select(nfds, &readfds, &writefds, &exceptfds, &timeout); 
    if ((rc < 0) && (errno == EINTR)) 
     continue; 
    else { 
     // some instructions 
    } 
} 

Если это не вариант для вас, вероятно, можно использовать pselect, который добавляет параметр в конец (sigmask), который определяет набор сигналов, которые должны быть заблокированы во время pselect(), см here

+0

Привет, Спасибо за ваше предложение. Я уже это сделал. но проблема заключается в том, что он продолжает циклически переключаться в select, так как он продолжает получать EINTR системой через каждые 20 мс, что является периодом таймера, запущенного в том же потоке. Итак, у меня есть функция выбора, которая продолжает работать, получая прерывается и работает снова, и в конечном итоге заканчивается ничего не читает в сокетах, просто продолжает цикл, выдавая прерывистый сигнал вызова. Любой способ избежать этого? Мне нужен таймер в том же потоке, я не могу игнорировать сигнал таймера, и я не могу заблокировать функцию выбора. Любой способ достижения обоих? – user2069669

+0

@ user2069669 добавлена ​​ссылка на pselect, вы можете использовать вместо select – Jekyll

2

Что вы делаете, это довольно странно. Посмотрим правде в глаза: таймеры - это древний и в большинстве своем устаревший механизм для работы. Практически все эти люди избегают сигналов, подобных чуме. Там нет ничего полезного в обратном вызове сигнала (вы, конечно же, не можете назвать что-то сложное, например, malloc), поэтому у вас должен быть какой-то способ получить уведомление таймера обратно от обработчика SIGALRM к основному потоку уже - вы На самом деле не Выполнение работы в обработчике сигналов вы?

Итак, у вас есть две тактики: используйте стандартный трюк с самоходкой, чтобы включить сигнал в событие на fd, «нормальный» способ обработки таких вещей, как SIGTERM, SIGINT и так далее. Вы вызываете socketpair или pipe, чтобы сделать трубу, а затем напишите байт в трубу от обработчика сигнала. Вы читаете байт от вас select цикл. Вы обычно записываете значение сигнала в качестве данных, но вы можете написать что-нибудь действительно.

Другая тактика (гораздо более разумная) заключается в том, чтобы избежать беспорядка с сигналами и setitimer полностью. setitimer является серьезным наследием и вызывает проблемы для всех видов вещей (например, он может вызывать такие функции, как getaddrinfo, ошибка, которая до сих пор не исправлена ​​в glibc (http://www.cygwin.org/frysk/bugzilla/show_bug.cgi?id=15819). Сигналы плохо для вашего здоровья. «тактика - использовать аргумент таймаута для select. У вас есть связанный список таймеров, объектов, которые вы используете для управления периодическими событиями в вашем коде. Когда вы вызываете select, вы используете в качестве таймаута самый короткий из оставшихся таймеров. Когда select вызов проверки, вы проверяете, истек ли какой-либо таймер, и вызовите обработчик таймера, а также обработчики для ваших fd-событий. Это стандартный цикл событий приложения. Таким образом, ваш код цикла, чтобы вы могли слушать события с таймером, а также fd -driven. Практически каждое приложение в вашей системе использует какой-то вариант этого механизма.

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