#c #serial-port #signals #posix
#c #последовательный порт #сигналы #posix
Вопрос:
У меня есть некоторый код, который считывает последовательный порт в моем pinguin-блоке. Код похож:
while ( 1 )
if ( select( handle 1, amp;h, NULL, NULL, amp;tm ) > 0 )
{
if( read( handle, amp;msg, 1 ) > 0 )
{
... tips and trixes
}
if ( gotWhatINeed ) break;
Код выполняется довольно долго, но если я попытаюсь немного подчеркнуть это, я начинаю постоянно получать ошибку 11 (EAGAIN), даже после завершения подчеркивания.
И теперь мне интересно, что я неправильно понимаю, из man 2 select я могу понять, что select возвращает количество байтов, доступных из дескриптора.
Возможно, представляет интерес то, что код всегда выполняется в отдельном потоке.
Основываясь на комментариях, я сейчас публикую более подробную информацию о коде.
В основном у меня есть
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
int main ( int argc, char **argv )
{
pthread_t scan_01
signal( 11, OnSignal );
pthread_mutex_init( amp;mut, NULL );
.....
pthread_create(amp;scan_01, NULL, (void *)readDevice, NULL);
pthread_detach(scan_01);
И метод, с помощью которого считывается устройство. TGM — это структура для хранения считанных данных. OnSignal просто регистрирует сигнал. _ примечание: вопрос
void *readDevice(void)
{
int r;
char b[256];
struct TGM tgm;
pthread_t new, self;
pthread_mutex_lock( amp;mut );
self = pthread_self( );
while( 1 )
{
FD_ZERO( amp;out );
FD_SET( fOut, amp;out );
tm.tv_sec = LOOP_DELAY;
tm.tv_usec = com_scan_time;
if ( select( fOut 1, amp; out, NULL, NULL, amp;tm ) > 0 )
{
r = readPort( fOut, 10, b, 1 );
pthread_mutex_unlock( amp;mut );
pthread_create( amp;new, NULL, (void *)readDevice, NULL );
pthread_detach( new );
iThreads ;
...
break;
}
}
self = pthread_self();
iThreads--;
pthread_exit( amp; self );
readPort похож, основная задача — «просто» перевести биты и байты в TGM.
int readPort(const int handle, char terminator, char b[256], int crc)
{
char msg;
fd_set h;
struct timeval tm;
do
{
FD_ZERO( amp;h );
FD_SET( handle, amp;h );
tm.tv_sec = LOOP_DELAY;
tm.tv_usec = com_scan_time;
if ( select( handle 1, amp;h, NULL, NULL, amp;tm ) > 0 )
{
if( read( handle, amp;msg, 1 ) > 0 )
{
if( msg == 3 ) // marks end of message
....
}
else
{
log( ERRLOG, "FAILED to read port (%d) %sn",
errno,
strerror( errno ) );
return -1;
}
Итак, в чем моя ошибка: D
Результат, который я получаю при вводе, примерно через 30 сообщений (значит, примерно через. 30 потоков — иногда немного больше, а иногда немного меньше — это)
НЕ УДАЛОСЬ прочитать порт (11), Ресурс временно недоступен
_Signal 11_
Спасибо, что уделили мне немного времени, я очень благодарен.
Комментарии:
1.
select()
возвращает количество доступных файловых дескрипторов ;read()
возвращает количество использованных байт .2. Кроме того, почему вы читаете только один байт за раз? Обратите внимание, что
EAGAIN
обычно это указывает на то, что вы пытались выполнить чтение из неблокирующего сокета, значит, там что-то еще напортачено.3.Вы имеете в виду код без ошибок
EAGAIN
, а не сигнал 11 (SIGSEGV
), верно? Это две совершенно не связанные вещи, которые указывают на совершенно разные проблемы. (В сторону: никогда не ссылайтесь на коды errno по их числовому значению, только по ихstrerror
тексту илиerrno.h
названию. Числа не согласованы между платформами или даже между процессорами с одним и тем же ядром (в отличие от меньших номеров сигналов)).4. Зак: Я думаю, и то, и другое. чтение возвращает 11, и, согласно man 2, это повторяется. но в этом случае также возникает сигнал 11.
5. Крисайкок: как в случае, если два потока одновременно читают один и тот же порт?
Ответ №1:
У вас есть 30 потоков, заблокированных в select (), которые все пытаются прочитать fOut, когда он становится доступным для чтения — затем проигравшие дают вам EAGAIN, когда буфер опорожняется?