mis@APL.STANFORD.EDU (Misha Pavel) (07/21/89)
I have a problem that probably reflects more my understanding of the low-level I/O than its inherent difficulty, but I am not shure how to proceed. I need to read a tty line and return immediately even if there is nothing in the system buffer for that tty. To do that I set the terminal in raw mode with the folowing settings: term.c_iflag = IGNBRK; term.c_oflag = 0; term.c_lflag = 0; term.c_cflag = B9600 | CS8 | CREAD | PARENB | PARODD; term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; I was hoping that the term.c_cc[VTIME] = 0 would do the job. But the system seems to be still waiting for at least one char. Is there any way to look at the system buffer and or return from read() when no input was generated? (Because of the real-time application I cannot afford to run a separate terminal process on my IRIS-2400). Any ideas? Thanks in advance Misha Pavel <mis@psych.Stanford.Edu>
moss@BRL.MIL ("Gary S. Moss", VLD/VMB) (07/28/89)
[Misha Pavel <mis@psych.Stanford.Edu> writes] < Is there any way to look at the system buffer and or return < from read() when no input was generated? Probably the better way to go, rather than mucking around with the terminal settings, is to use fcntl() as follows: Where fd is a file descriptor returned from creat(), open(), dup(), fcntl(), or pipe(). #include <fcntl.h> (void) fcntl( fd, F_SETFL, O_NDELAY ); /* to check the buffer... */ if( read( fd, bufptr, bytes ) == 0 ) ; /* nothing to read */ To be portable to BSD systems, the following is more correct: got = read( fd, bufptr, bytes); #ifdef BSD if( got == -1 && errno == EWOULDBLOCK ) got = 0; /* act like System V */ #endif if( got == 0 ) ; /* nothing to read */ Do a 'man fcntl' for more info. -moss
vjs@rhyolite.wpd.sgi.com (Vernon Schryver) (07/29/89)
In article <8907201857.aa12017@SMOKE.BRL.MIL>, mis@APL.STANFORD.EDU (Misha Pavel) writes: > ... > I was hoping that the term.c_cc[VTIME] = 0 would do the job. > But the system seems to be still waiting for at least one char. > > Is there any way to look at the system buffer and or return > from read() when no input was generated? > ... > > Misha Pavel <mis@psych.Stanford.Edu> System V has a confusing notion of VTIME/VMIN. It likes to wait for at least one character. I seem to recall that there is a combination which does not wait, but there is no reason to suffer the pain of reading the SVID (the only place I know where it is half way documented), or of reading either SGI's stty_ld.c or the standard SVR3 line discipline code. You could use the FIONNBIO ioctl(2) on an FD that is a tty or socket. I would use select(2) instead. Select(2) has always worked on streams (tty's) and sockets. It allows fine grain timeouts and simultaneous polling of lots of FD's, for reading and/or writing. It now works on everything. Now is 3.2, or maybe some version of 3.1. It was added to lboot(1), cdev[], etc. seemingly a long time ago. Vernon Schryver Silicon Graphics vjs@sgi.com
jmb@patton.sgi.com (Jim Barton) (07/31/89)
In article <8907201857.aa12017@SMOKE.BRL.MIL>, mis@APL.STANFORD.EDU (Misha Pavel) writes: ... > I need to read a tty line and return immediately > even if there is nothing in the system buffer for that tty. > To do that I set the terminal in raw mode with the folowing > settings: > > term.c_iflag = IGNBRK; > term.c_oflag = 0; > term.c_lflag = 0; > term.c_cflag = B9600 | CS8 | CREAD | PARENB | PARODD; > term.c_cc[VMIN] = 1; > term.c_cc[VTIME] = 0; > ... > Misha Pavel <mis@psych.Stanford.Edu> Several others have posted valid solutions to this problem, but there is one valid one which is portable (although somewhat ugly) and used by many programs out there. You have the VMIN and VTIME settings backwards. The proper way to do this is to set: term.c_cc[VMIN] = 0; term.c_cc[VTIME] = 1; This tells the terminal driver to return if no characters have arrived in the last 1/10 second, thus your program would sleep for 1/10 of a second each time it polled the variable. The proper way to read a single character is then to perform the read as: if (read(fd, &c, 1) == 1) /* got a character */ ... This style of handling the terminal is oriented towards efficient yet responsive data passing. For instance, let's say I write a program which reads from the tty line and writes to a file (or a pty, for instance). In that case, I could set up a small buffer to take either a maximum number of characters or time out after a certain point: term.c_cc[VMIN] = 0; term.c_cc[VTIME] = 2; ... while ((count = read(ifd, buf, 10) > 0) write(ofd, buf, count); This makes for high throughput while still insuring that single characters make it through quickly. It is useless in real-time applications. As Vernon and Mike pointed out, IRIX is fairly rich in ways to do this operation while still being real-time. -- Jim Barton Silicon Graphics Computer Systems "UNIX: Live Free Or Die!" jmb@sgi.sgi.com, sgi!jmb@decwrl.dec.com, ...{decwrl,sun}!sgi!jmb
moss@BRL.MIL ("Gary S. Moss", VLD/VMB) (08/01/89)
[Jim Barton writes] < Several others have posted valid solutions to this problem, but there is one < valid one which is portable (although somewhat ugly) and used by many < programs out there. < < You have the VMIN and VTIME settings backwards. The proper way to do < this is to set: < < term.c_cc[VMIN] = 0; < term.c_cc[VTIME] = 1; I don't believe that this is portable, except on System V based machines. It will work on some BSD-based systems, but not all, especially older implementations. For example, here is an excerpt from the termio(4V) manual page on my Sun (Release 3.2): " 3. The MIN and TIME values supported by other implementations can be set, but this has no effect on the terminal driver. The driver behaves as if MIN were 1 and TIME were 0." Basic BSD systems use the sgtty structures rather than termio; though later versions have some compatibility with System V built in, you may not get the behavior you want. -moss
jmb@patton.sgi.com (Jim Barton) (08/02/89)
In article <8908011000.aa22873@VMB.BRL.MIL>, moss@BRL.MIL ("Gary S. Moss", VLD/VMB) writes: > [Jim Barton writes] ... > I don't believe that this is portable, except on System V based machines. > It will work on some BSD-based systems, but not all, especially older > implementations. For example, here is an excerpt from the termio(4V) manual > page on my Sun (Release 3.2): ... > -moss Sorry, I meant portable to other System V machines. Of course this is nonsense on non-conforming implementations. Bezerkely has better ways to do this, and IRIX has picked those up. -- Jim Barton Silicon Graphics Computer Systems "UNIX: Live Free Or Die!" jmb@sgi.sgi.com, sgi!jmb@decwrl.dec.com, ...{decwrl,sun}!sgi!jmb