LINUX.ORG.RU

Помогите разобраться с select (C)


0

0

Вот такой вот вопрос. Есть стандартный слегка модифицированный пример из мануала по select, в котором происходит ожидание ввода из стандартного устройства 10 секунд:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>

int main() {
struct timeval timeout;
char string[BUFSIZ];

int len = 0, retval = 0;
fd_set readfd;

timeout.tv_sec = 10;
timeout.tv_usec = 0;

printf("You have 10 seconds to enter your name: ");

FD_ZERO(&readfd);
FD_SET(0, &readfd);

retval = select(1, &readfd, NULL, NULL, &timeout);

if (retval > 0)
{
printf("data are ready\n");
len = read(0, string, sizeof(string));
}
else
{
printf("no input after 10 secs\n");
}

printf("len = %d\n", len);
printf("%s - you're speedy!\n", string);

return (EXIT_SUCCESS);
}

И вывод программы примерно следующий:
andrey@linux:~/WORK/timer_test_2> ./test
andrey<ENTER> <--- это мы вводим
You have 10 seconds to enter your name: data are ready
len = 7
andrey
- you're speedy!

И вопросов, собственно, несколько:
1. почему первый printf срабатывает ПОСЛЕ ввода строки, а не до?
2. почему возврат из select происходит после ввода целой строки, а не после ввода одного символа? ведь данные уже поступили... Есть подозрения, что это связано с настройками терминала, если это так, то подскажите, плз, как это побороть.

надо fflush(stdout) сразу после первого printf делать

rincewind
()

> Есть подозрения, что это связано с настройками терминала, если это так, то подскажите, плз, как это побороть.

недавно пробегала тема, там накидали рецептов:

http://www.linux.org.ru/view-message.jsp?msgid=2027234

dilmah ★★★★★
()

> 2. почему возврат из select происходит после ввода целой строки, а не после ввода одного символа?

Потому что драйвер терминала по умолчанию ждёт перевода строки и потом посылает приложению сразу всю введённую строку.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Спасибо, небольшие изменения с настройками терминала и fflush(stdout) действительно помогли.

Iceman82
() автор топика

И вот еще вопрос в догонку. В мане по select написано, что он не блокирует операции чтения/записи. И в связи с этим вопрос - select сам переводит соответсвующие дескрипторам устройства ввода/вывода в неблокирующий режим, или он их просто каким-то образом "слушает" на предмет новых данных, не изменяя режима работы?

Iceman82
() автор топика
Ответ на: комментарий от Iceman82

> И вот еще вопрос в догонку. В мане по select написано, что он не блокирует операции чтения/записи. И в связи с этим вопрос - select сам переводит соответсвующие дескрипторам устройства ввода/вывода в неблокирующий режим, или он их просто каким-то образом "слушает" на предмет новых данных, не изменяя режима работы?

сам по себе select(2) к режиму чтения/записи block/non-block и операциям чтения/записи отношения не имеет. он всего лишь делает запрос в ядро на тему "заблокируй мой процесс на внутренней очереди событий данного устройства до тех пор, пока в ней не появится интересующее меня событие из заданного набора read/write/exception". после того, как событие появилось в очереди устройства, select разблокируется ядром и событие возвращается вызывающему процессу. при этом каким образом и когда именно событие будет удалено из очереди зависит от конкретного устройства. обычно события о готовности данных удаляются после вызова read(2), но в общем и целом это отдано на откуп конкретному драйверу.

это я к тому, что связь между select(2) и read(2)/write(2) жёстко ни кем не регламентируется и в общем случае может быть весьма нелинейной в зависимости от драйвера конкретного устройства.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> это я к тому, что связь между select(2) и read(2)/write(2) жёстко ни кем не регламентируется и в общем случае может быть весьма нелинейной в зависимости от драйвера конкретного устройства.

Т.е., если я правильно понял, конкретная реакция устройства на select(2) зависит от его драйвера?

Я это к чему все спрашиваю - есть самописный драйвер одного устройства, который передает данные по последовательному порту. И пока этот драйвер ничего не знает ни про nonblocking read, ни про select и poll. Тогда получается, что если я хочу с этим устройством из user-space программы работать через select(2) (или poll(2)), то такую возможность надо в драйвере обязательно предусмотреть?

Iceman82
() автор топика
Ответ на: комментарий от Iceman82

> Т.е., если я правильно понял, конкретная реакция устройства на select(2) зависит от его драйвера?

именно так. конечно, есть общие соглашения о том, каким образом должно быть сброшено событие разблокировавшее селект, но в принципе никто не мешает драйверу пойти своим путём.

> Я это к чему все спрашиваю - есть самописный драйвер одного устройства, который передает данные по последовательному порту. И пока этот драйвер ничего не знает ни про nonblocking read, ни про select и poll. Тогда получается, что если я хочу с этим устройством из user-space программы работать через select(2) (или poll(2)), то такую возможность надо в драйвере обязательно предусмотреть?

да, поддержка poll(2)/select(2) должна быть явным образом реализована в драйвере. если её нет, i.e. если драйвер не устанавливает нужные калбеки и не обрабатывает соотв. функции, ядро на вызов select(2) просто вернёт ошибку a'la EINVAL.

// wbr

klalafuda ★☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.