LINUX.ORG.RU

Ответ на: re от rh9

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

cvv ★★★★★
() автор топика

Приложение какое - многопоточное или все в одном процессе? select() сработал - т е произошло событие на дескрипторе и не факт, что это данные. Может быть например ошибка

anonymous
()

У меня на СОМ порте тоже такие же глюки, на tcp-шном дискрипторе всё было нормально.

binr ★★
()

Интересно, а что будет делать _блокирующий_ read()?

Die-Hard ★★★★★
()

Если ты читаешь в raw mode, проверь, что у тебя в c_cc[VMIN] и c_cc[VTIME]. Детальней смотри в Serial Programming Guide
for POSIX Operating Systems
http://www.easysw.com/~mike/serial/serial.html
в параграфе "Setting Read Timeouts".

Также это неплохо описано в книжке Linux Application Development
(Johnson, Troan), примеры оттуда есть в Инете свободно.
Наверное у Стивенса в тоже APUE было, но сейчас под рукой нету.
Ну и man termios в руки.

Если кратко:

1. если VTIME==0, read() блокируется, пока не будет доступно VMIN байт
2. если VMIN==0, read() вернется не позднее, чем через VTIME десятых
секунд и если ни фига не прочитано - вернет 0 (причем это не будет
означать EOF)
3. если VTIME!=0 и VMIN!=0 то ... не помню наизуть... что-то там
нетривиальное, прочитай сам
4. если VTIME==0 и VMIN==0 то read() в любом случае не блокирующий
и может вернуть 0 если нет данных.

HTH

нетривиальное, прочитай сам

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

>Если ты читаешь в raw mode,

читаю в raw mode.

>проверь, что у тебя в c_cc[VMIN] и c_cc[VTIME].

я ж писал НЕБЛОКИРУЮЩИЙ read(). Его НЕЛЬЗЯ сделать неблокирующим иначе как установив c_cc[VMIN]=0 и c_cc[VTIME]=0;

>Детальней смотри в Serial Programming Guide for POSIX Operating Systems

изучил почти как "Отче Наш".

>4. если VTIME==0 и VMIN==0 то read() в любом случае не блокирующий и может вернуть 0 если нет данных.

а если мне select() вернул что данные есть?????

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

Значит "слишком быстро работаешь". Поставь перед забором данных паузу и посмотри что будет. А также попробуй поменять на блокирующий и посмотреть тчо полчится.

anonymous
()
Ответ на: комментарий от cvv

> читаю в raw mode.

Замечательно ;-)

> я ж писал НЕБЛОКИРУЮЩИЙ read(). Его НЕЛЬЗЯ сделать неблокирующим
> иначе как установив c_cc[VMIN]=0 и c_cc[VTIME]=0;

Конечно можно. Установив O_NONBLOCK для файл-дескриптора.

> изучил почти как "Отче Наш".

Чесслово - незаметно. Раз ты _сам_ установил VMIN=VTIME=0
то очевидно, read() _может_ вернуть 0.

> а если мне select() вернул что данные есть?????

Нет, ты не так понял select(). select() не сказал, что данные есть,
он лишь сказал, что ты можешь сделать read() и этот read() вернется
мгновенно, без блокировки. И это обещание он выполнил. Другое дело,
что ты так сконфигурировал драйвер терминального I/O (VTIME=VMIN=0),
что он рапортует о готовности к чтению даже при отсутствии данных
(и честно возвращает 0). Доступно?

Рекомендую попробовать так:
1. VMIN=1
2. VTIME=0

Теперь твой файл-дескриптор будет вести себя примерно так же,
как если бы это был pipe или там socket. То есть делай его
O_NONBLOCK, используй его в select() и так далее.

... давно это был... надеюсь, ничего не перепутал...

HTH





Onanim
()
Ответ на: re от rh9

speed 57600 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 0; -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

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


Вдогонку:

> а если мне select() вернул что данные есть?????

$ man 2 read
....
Three independent sets of descriptors are watched. Those listed in
readfds will be watched to see if characters become available for
reading (more precisely, to see if a read will not block...
...

Фтыкаем в слова "more precisely, to see if a read will not block"
до просветления ;-)

HTH

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

>... давно это был... надеюсь, ничего не перепутал...

перепутал.

>Конечно можно. Установив O_NONBLOCK для файл-дескриптора.

линукс на этот флаг ПОЛНОСТЬЮ забивает. что есть что нету а драйвер ком-порта смотрит только на VMIN и VTIME. кажись ман open || man fcntl.

>Раз ты _сам_ установил VMIN=VTIME=0 то очевидно, read() _может_ вернуть 0.

c этим никто не спорит. Вопрос не в этом.

>> а если мне select() вернул что данные есть?????

>Нет, ты не так понял select(). select() не сказал, что данные есть, он лишь сказал, что ты можешь сделать read() и этот read() вернется мгновенно, без блокировки. И это обещание он выполнил.

а что он мне тогда сказал если я его просил ничего другог мне не сообщать????

>Другое дело, что ты так сконфигурировал драйвер терминального I/O (VTIME=VMIN=0), >что он рапортует о готовности к чтению даже при отсутствии данных (и честно возвращает 0). Доступно?

кажись 100% враньё. VTIME, VMIN никаким образом не влияют на поведение select() только на read(). Select() сам неплохо знает как себя вести в конкретной ситуации.

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

>Фтыкаем в слова "more precisely, to see if a read will not block" до просветления ;-)

спасибо, как-то раньше я этого не замечал. Хотя описанная мною ситуация проявляется гдето один раз на несколько десятков тысяч селектов() при неопределённых обстоятельствах.

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

2 cvv:

> > Конечно можно. Установив O_NONBLOCK для файл-дескриптора. 

> линукс на этот флаг ПОЛНОСТЬЮ забивает. что есть что нету а драйвер 
> ком-порта смотрит только на VMIN и VTIME. кажись ман open || man 
> fcntl.

Ржунимагу! То есть Linux не поддерживает O_NONBLOCK? Что, вообще
не поддерживает? Или только для terminal i/o?

Ладно, сейчас попробуем.
Для начала без O_NONBLOCK:

$ cat ttt.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

#define BAUDRATE B38400
#define _POSIX_SOURCE 1

main()
{
    int fd, c;
    struct termios newtio;

    fd = open("/dev/tty9", O_RDWR | O_NOCTTY); 
    if (fd <0) {perror("/dev/tty9"); exit(-1); }
    printf("Opened...\n");

    bzero(&newtio, sizeof(newtio));
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
    newtio.c_iflag = IGNPAR;
    newtio.c_oflag = 0;
    newtio.c_lflag = 0;
    newtio.c_cc[VTIME] = 0; 
    newtio.c_cc[VMIN]  = 1;

    tcflush(fd, TCIFLUSH);
    tcsetattr(fd,TCSANOW, &newtio);


    while (1)
    {   
        char buf[16];
        int n = read(fd,buf,sizeof(buf));
        if (n>=0) printf("read() returned %d\n", n);
        else      perror("read()");
    }
}
$ make ttt
cc     ttt.c   -o ttt
$
$ ./ttt
Opened... 
   # теперь идем на /dev/tty9 и вводим несколько символов
read() returned 1
read() returned 1
read() returned 1
read() returned 1
^C
$

ОК, все как ожидалось - блокирующий ввод.

Теперь меняем 
   open("/dev/tty9", O_RDWR | O_NOCTTY);
на 
   open("/dev/tty9", O_RDWR | O_NOCTTY | O_NONBLOCK);

$ make ttt
cc     ttt.c   -o ttt
$ ./ttt
Opened...
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
read(): Resource temporarily unavailable
^C
$

Как видим, read() не блокируется, сплошным потоком посыпался вывод
от perror() с вполне логичным сообщением - "Resource temporarily 
unavailable"

Ну и где же не работает O_NONBLOCK ?

Срочно иди учиться!

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

>Срочно иди учиться!

век живи - век учись

крайне странная ситуация:

man open:
     O_NONBLOCK or O_NDELAY
          This mode need not have any effect on files other than FIFOs.

то что на других системах он имеет эффект для ком-порта это мне известно, но чтобы он работал под линуксом первый раз вижу.

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

cvv:

> This mode need not have any effect on files other than FIFOs.

Это -- неудачный (в стилистическом плане) намек на то, что большинство _локальных_ файловых систем игнорируют эти флаги для "настоящих" файлов.

Die-Hard ★★★★★
()
Ответ на: комментарий от cvv


> крайне странная ситуация:
>
> man open:
> O_NONBLOCK or O_NDELAY
> This mode need not have any effect on files other than FIFOs.
>
> то что на других системах он имеет эффект для ком-порта это мне
> известно, но чтобы он работал под линуксом первый раз вижу.

"Не верь глазам своим!" (C)
Ну дык там и про сокеты ничего не написано, но ты же надеюсь
не сомневаешься, что для сокетов O_NONBLOCK работает ;-)

Скорее это объясняется тем, что поддержка O_NONBLOCK зависит от
конкретного типа файл-дескриптора, и man open не может перечислить
все возможные (и будущие) варианты дескрипторов (разные сокеты, пайпы,
devices...).

Например даже в SUS
(http://www.opengroup.org/onlinepubs/009695399/functions/open.html)
описан эффект O_NONBLOCK только для FIFO,
character devives и block devices. Для всего остального - "Otherwise,
the behavior of O_NONBLOCK is unspecified."

Если честно, то мой опыт в serial programming ограничивается UnixWare
и Solaris но было бы странно, если бы Linux отличался в
фундаментальных вещах типа интерпретации O_NONBLOCK.

HTH

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

всем спасибо что-то прояснил. Хотя я ещё не совсем доконца понял поведение select()

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

>Ну дык там и про сокеты ничего не написано, но ты же надеюсь не сомневаешься, что для сокетов O_NONBLOCK работает ;-)

а разве сокеты при помощи open() создаются???

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

Onanim (03.11.2005 16:05:24):

> > а разве сокеты при помощи open() создаются???

При чем тут open()? O_NONBLOCK вполне fcntl() выставляется.

>Каюсь, пример неудачный :-)))

Как раз самый удачный!

Именно O_NONBLOCK для сокета -- один из _немногих_ примеров, когда имеет смысл использовать неблокирующее _чтение_ совместно с select():

Из man accept:

To ensure that accept never blocks, the passed socket s needs to have the O_NONBLOCK flag set (see socket(7)).

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

> Именно O_NONBLOCK для сокета -- один из _немногих_ примеров, когда
> имеет смысл использовать неблокирующее _чтение_ совместно с select:
> Из man accept:
>
> To ensure that accept never blocks, the passed socket s needs to
> have the O_NONBLOCK flag set (see socket(7)).
>

Да, AFAIK это единственный случай, когда дескриптор, отмеченный
select()'ом как read-ready может оказаться не ready. Но я все
равно ставлю O_NONBLOCK для _всех_ дескрипторов, для которых I/O
регулируется select()'ом... это паранойя такая :-)))




Onanim
()
Ответ на: комментарий от Die-Hard

>При чем тут open()?

при том что мы обсуждаем man open

>O_NONBLOCK вполне fcntl() выставляется.

никто не спорит, но это не в тему

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


BTW эта недоговорочка насчет O_NONBLOCK в Linux man open
наверное вызвана тем, что основной документацией должна
теперь быть info а на man'ы забили.
Попробовал вот из любопытства:

$ info open
...
-- Macro: int O_NONBLOCK
This prevents `open' from blocking for a "long time" to open the
file. This is only meaningful for some kinds of files, usually
devices such as serial ports; when it is not meaningful, it is
harmless and ignored. Often opening a port to a modem blocks
until the modem reports carrier detection; if `O_NONBLOCK' is
specified, `open' will return immediately without a carrier.
...
$

Вот тут "devices" и даже "serial ports" явно указаны.

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

в SUSv2 написано тоже самое

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

Onanim :

> Но я все равно ставлю O_NONBLOCK для _всех_ дескрипторов, для которых I/O регулируется select()'ом... это паранойя такая :-)))

Кстати, зря.

Так тебе придется ВСЮ логику самому писАть. А, между тем, часто бывает достаточно только иногда select()'ом read-дескрипторы проверять, а в транзакциях полагаться на блокирующие свойства read().

write-дескрипторы, действительно, имеет смысл всегда делать неблокирующими.

Die-Hard ★★★★★
()
Ответ на: комментарий от Onanim

Насчет man open я где-то читал (не помню, где) обсуждение. Типа, выяснили, что эта строчка перекочевала из некоторого текста, где она звучала в контексте того, что современные файловые системы настолько быстры, что O_NONBLOCK там не имеет никакого смысла и поэтому игнорируется для всего, кроме пайпов.

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

Die-Hard :

>> Onanim :

>> Но я все равно ставлю O_NONBLOCK для _всех_ дескрипторов, для
>> которых I/O регулируется select()'ом... это паранойя такая :-)))

> Так тебе придется ВСЮ логику самому писАть. А, между тем, часто
> бывает достаточно только иногда select()'ом read-дескрипторы
> проверять, а в транзакциях полагаться на блокирующие свойства
> read().

Ни фига не понял. Если я для каких-то дескрипторов спрашиваю
у select() "можно уже читать/писать?" это очевидно значит, что
я ни в коем случае не хочу блокировки read()/write(). Для этих
дескрипторов. Поэтому я ставлю O_NONBLOCK для них - хотя это
реально нужно только в случае accept(). Но я ставлю на всякий
случай.
Это не значит, что у меня в процессе _все_ дескрипторы O_NONBLOCK.
Я ж вроде русским языком написал - "ставлю O_NONBLOCK для _всех_ дескрипторов, для которых I/O регулируется select()ом".
А те дескрипторы, которые никакими select() не мониторятся -
те могут быть любыми и использоваться как угодно - хоть
блокирующими read()/write() а хоть и AIO.
BTW, а что такое "транзакции" в данном контексте?

> write-дескрипторы, действительно, имеет смысл всегда делать
> неблокирующими.

Тоже ниасилил. O_NONBLOCK действует и на запись, и на чтение.
Как ты себе представляешь сокет, у которого на запись стоит
O_NONBLOCK а на чтение - нет? :-/


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

Извиняюсь, я неявно перевел разговор с сокетов на дескрипторы вообще.

> Это не значит, что у меня в процессе _все_ дескрипторы O_NONBLOCK. Я ж вроде русским языком написал - "ставлю O_NONBLOCK для _всех_ дескрипторов, для которых I/O регулируется select()ом".

Ну, представь, что ты оперируешь блоками данных, которые к тебе через пайп лезут. Каждый блок требует более одного read(). Если с другой стороны начали писАть, то тебе нельзя отвлекаться на других, пока весь блок не прочитаешь. Но, вообще говоря, одновременно к тебе могут сразу много писателей постучаться.

Описанная ситуация у меня наиболее часто почему-то встречается, BTW. Я слушаю select()'ом толпу блокирующих дескрипторов, а потом форкаюсь (или в пул кидаю), и спокойно полагаюсь на блокирующий read().

> Тоже ниасилил. O_NONBLOCK действует и на запись, и на чтение. Как ты себе представляешь сокет, у которого на запись стоит O_NONBLOCK а на чтение - нет? :-/

Я не про сокеты, а вообще про дескрипторы.

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

> Описанная ситуация у меня наиболее часто почему-то встречается,
> BTW. Я слушаю select()'ом толпу блокирующих дескрипторов, а потом
> форкаюсь или в пул кидаю), и спокойно полагаюсь на блокирующий
> read().
>

Асилил :-) Да, при таком дизайне ты конечно прав в отношении
O_NONBLOCK. Но у этой модели есть ограничение в плане расширения возможных транспортов. То есть у тебя и транспортный тред (тот, где
select), и worker threads должны уметь работать с транспортным
объектом (файл-дескриптором). Этого достаточно, пока клиенты
не захотят испозьзовать не просто TCP, а скажем SSL/TLS или там
IBM MQ Series или X.25. Тогда ты устанешь модифицировать свои
worker threads, чтобы они это все умели читать/писать :-O

Поэтому удобно транспорты сделать как совершенно отдельные модули,
которые инкапсулируют всю работу с транспортом (и читают, и пишут,
и все остальное). С worker thread'ами они обмениваются данными неким
унифицированным образом, например через очереди. Короче, наверное
долгое использование ACE (http://www.cs.wustl.edu/~schmidt/ACE.html)
наложило на меня свой отпечаток - хочется все максимально разделить
и инкапсулировать :-)))

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

Onanim :

> у этой модели есть ограничение в плане расширения возможных транспортов.

Ты говоришь про neteworking, да еще жутко scalable, а я имел в виду Inter Proc. Comm. через неименованные пайпы.

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

> Ты говоришь про neteworking, да еще жутко scalable, а я имел
> в виду Inter Proc. Comm. через неименованные пайпы.
>

Дык я разве настаиваю? Каждой задаче - свой инструмент,
как говорится - "get the right tool". :-)

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