|
Home > Archive > Unix Programming > April 2007 > Please clarify what happens when doing the following with fcntl and open
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Please clarify what happens when doing the following with fcntl and open
|
|
| Andrew Falanga 2007-04-17, 7:19 pm |
| Hi,
I'm trying to weed out some problems in the code I'm writing for a
serial application. I'm using the POSIX termios structures for this
program (although, not much that I'm about to ask will directly
reference this).
The first and most important question, I think, is do the functions
open, specifically the flags argument not anything else, and the fcntl
function operate on the same data structures describing the file
descriptor? The reason I ask is as follows:
in my code I have this
fd = open( dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY );
// then later on, but still in the ctor for this class
if( fcntl( fd, F_SETFL, 0 ) < 0 ) {
// throw an error saying what happened
}
Does this call to fcntl stomp all I did in the open call? Basically,
on the reading end, I'm always setting VTIME to 0 and VMIN to a non-
zero value because I want to wait for a specific amount of data to be
available. Setting the no-delay (O_NDELAY) flag would seem to negate
this. Therefore, I clear the flags, but does the call to fcntl stomp
everything else too?
Reading the manual pages would seem to indicate that part of this
structure is not accessible to fcntl. To be sure, I looked in /usr/
include/bits/fcntl.h (for Linux) and found the following comments next
to the constants like O_NOCTTY, /* not fcntl */. This would seem to
further the idea that, if the two functions manipulate a common data
structure, they do not overlap 100%. Is this true?
On a different note, What approaches would be good for constructing a
timeout mechanism for waiting for data on the reading end? The
program operates in two modes; a standard mode and a flood mode. In
standard, the flow of data is bidirectional, but is unidirectional in
the other. In flood mode, I want the program to timeout if no data
ever arrives. If my understanding of the VMIN member to the c_cc
array is correct, this is only an inter-byte timer meaning that it
only works once data has begun to be received. What if data never
comes?
Andy
| |
| Stephane CHAZELAS 2007-04-17, 7:19 pm |
| 2007-04-17, 12:56(-07), Andrew Falanga:
[...]
> fd = open( dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY );
>
> // then later on, but still in the ctor for this class
> if( fcntl( fd, F_SETFL, 0 ) < 0 ) {
> // throw an error saying what happened
> }
>
> Does this call to fcntl stomp all I did in the open call? Basically,
> on the reading end, I'm always setting VTIME to 0 and VMIN to a non-
> zero value because I want to wait for a specific amount of data to be
> available. Setting the no-delay (O_NDELAY) flag would seem to negate
> this. Therefore, I clear the flags, but does the call to fcntl stomp
> everything else too?
There's an answer to your question in my man page of fcntl on
Linux:
On Linux this command can only change the O_APPEND, O_ASYNC,
O_DIRECT, O_NOATIME, and O_NONBLOCK flags.
(O_NONBLOCK being the same as O_NDELAY),
So fcntl(F_SETFL, 0) will only clear O_NDELAY in your case.
> On a different note, What approaches would be good for constructing a
> timeout mechanism for waiting for data on the reading end? The
> program operates in two modes; a standard mode and a flood mode. In
> standard, the flow of data is bidirectional, but is unidirectional in
> the other. In flood mode, I want the program to timeout if no data
> ever arrives. If my understanding of the VMIN member to the c_cc
> array is correct, this is only an inter-byte timer meaning that it
> only works once data has begun to be received. What if data never
> comes?
[...]
The VMIN/VTIME stuff are for ioctls to the terminal driver, so
that's one layer underneath the fcntl.
Basically, if you do a TCSETSW ioctl with VMIN=2 and VTIME=0
(with ~ICANON), the terminal driver will not make anything
available to any read() until 2 characters are coming from the
line.
So, with O_NDELAY, a read() will block until 2 characters are
received, and with O_NDELAY a read will return -1 (EAGAIN) until
2 characters are received
With VMIN=10 VTIME=10 ~ICANON (again, that's only for terminal
devices) there'll be nothing to be read (so read() will block or
will return -1 EAGAIN depenind on O_NDELAY) until either 10
characters have been received, or at least one character has
been received and no character have been received in the past 10
ds (1 s).
If you want a timeout on a read, best is probably to use poll()
or select(), the tcsetattr will only work on terminals.
--
Stéphane
| |
| Andrew Falanga 2007-04-17, 7:19 pm |
| On Apr 17, 2:26 pm, Stephane CHAZELAS <this.addr...@is.invalid> wrote:
> 2007-04-17, 12:56(-07), Andrew Falanga:
> [...]
>
>
>
>
> There's an answer to your question in my man page of fcntl on
> Linux:
>
> On Linux this command can only change the O_APPEND, O_ASYNC,
> O_DIRECT, O_NOATIME, and O_NONBLOCK flags.
>
> (O_NONBLOCK being the same as O_NDELAY),
>
> So fcntl(F_SETFL, 0) will only clear O_NDELAY in your case.
>
>
> [...]
>
> The VMIN/VTIME stuff are for ioctls to the terminal driver, so
> that's one layer underneath the fcntl.
>
> Basically, if you do a TCSETSW ioctl with VMIN=2 and VTIME=0
> (with ~ICANON), the terminal driver will not make anything
> available to any read() until 2 characters are coming from the
> line.
>
> So, with O_NDELAY, a read() will block until 2 characters are
> received, and with O_NDELAY a read will return -1 (EAGAIN) until
> 2 characters are received
>
With which one did you mean without O_NDELAY?
Andy
| |
| Stephane CHAZELAS 2007-04-18, 7:19 am |
| 2007-04-17, 13:34(-07), Andrew Falanga:
[...]
[...][vbcol=seagreen]
>
> With which one did you mean without O_NDELAY?
[...]
Well, the O_NONBLOCK gives some kind of a hint doesn't it? 
Note that EAGAIN can sometimes be EWOULDBLOCK, though on Linux,
they are generally the same.
--
Stéphane
| |
| Stephane CHAZELAS 2007-04-18, 7:19 am |
| 2007-04-17, 13:34(-07), Andrew Falanga:
[...][vbcol=seagreen]
[...]
Sorry, I was wrong.
Though that's true on Solaris or HPUX at least, it is not on
Linux. There, the O_NDELAY causes characters to be delivered as
soon as they arrive whatever the value of VMIN, see:
stty min 10 time 0 -icanon; strace -e read PERL -MFcntl -e '
fcntl(STDIN, F_SETFL, O_NONBLOCK | fcntl(STDIN, F_GETFL, 0));
while ($_ = <> || $!{EAGAIN}) {sleep(1)}'
min 10 would mean that you need to enter 10 characters before
read() (<> ) gets anything, but running that command shows that
as soon as you type even only one, it is available to the next
read.
Wonder if that could be considered as a bug in Linux.
--
Stéphane
|
|
|
|
|