Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!seismo!ut-sally!hitchens From: hitchens@ut-sally.UUCP (Ron Hitchens, TP Repairman) Newsgroups: comp.unix.questions Subject: Re: Keyboard Input (Revised Question) ... Message-ID: <8578@ut-sally.UUCP> Date: Tue, 28-Jul-87 01:33:23 EDT Article-I.D.: ut-sally.8578 Posted: Tue Jul 28 01:33:23 1987 Date-Received: Wed, 29-Jul-87 04:09:29 EDT References: <1043@bucsb.bu.edu.UUCP> <8569@ut-sally.UUCP> <1021@ius1.cs.cmu.edu> Reply-To: hitchens@godzilla.cs.utexas.edu (Ron Hitchens) Organization: Syscalls R Us Lines: 129 Keywords: Keyboard Summary: use select() when appropriate In article <1021@ius1.cs.cmu.edu> edw@ius1.cs.cmu.edu (Eddie Wyatt) writes: }In article <8569@ut-sally.UUCP>, hitchens@godzilla.cs.utexas.edu (Ron Hitchens, Sun Wiz) writes: }> ...this is a job for select()... } If your talking about my posting of "ready_to_read" for determining }if a characters are ready to read, there is a reason why it doesn't used }"select". Plain in simple, select is a dog of a system call. When I measure }the time it takes to call both select and ioctl on a fd associated with a }socket, I found ioctl FNREAD to be about 3 times as fast. Ya gotta point, Eddie. Select does indeed incur quite a bit more overhead than an ioctl does. Though in fairness select is more flexible and works at a higher level than an ioctl does. In looking at this again, I think I made an assumption that the code would want to do periodic processing, while also watching the keyboard for input. This may not be the case, if you want to spend as much time as possible computing, but also notice that a key has been pressed, using a FIONREAD ioctl is quicker and less expensive. But if you want to go to sleep until either something is ready to read or a time interval expires, select is clearly better. This is in fact multiplexing, multiplexing a timer and an fd. This is a big win over polling loops for that sort of thing. } To the orignal poster, you want to run both read_to_read or select with }CBREAKs on. Yeah, and remember to reset the tty modes before you exit. You may also want to catch INT and QUIT signals so that you can reset the modes if you're interrupted. } BTW select is only better than ioctl for determining if a SINGLE port }has characters on it to read from, in that you can specify a time out value if }needed. May I also sugguest you read the man page entry for "select". The }synopsis specificly says the call is intended for multiplexing. Polling a }single line doesn't constitute multiplexing, through the system call "select" }can obviously be used for such operations. Agreed. Polling an fd with a timeout is what I had in mind. This is not always what is desired, but is a good coding practice for interactive applications. It allows you to surrender control to the kernel, so that other processes can run, and have it wake you up when one of two (or more) conditions is met. Again, I agree that select is not a good choice for doing a straight poll on a single fd, though it can be done. A direct ioctl is less expensive for that. }> loop () }> { }> static struct timeval timer = {REFRESH_DEFAULT, 0}; }> char c; }> int inmask, nfds; }> }> timer.tv_sec = refresh_time; /* settable on cmd line */ }> while (1) { }> show_stat (); /* do it */ }> inmask = 1; /* gotta set the mask always */ } ^^^^^^^^^^^^^^^^^^^^ } A mood point here. If you are using BSD 4.2 this should be: } inmask = (1<<(fileno(stdout))); } } In BSD 4.3 this should be : } { } fd_set inmask; } ..... } } FD_SET(fileno(stdout),&inmask); } ......... } } Right, except that I'm using stdin, not stdout. The hardcoded 1 (shame on me!) is the bit for fd 0 which is (usually) stdin. Sorry about that, this is ancient code and I should know better. }> if ((nfds = select (32, &inmask, 0, 0, &timer)) < 0) { }> printf ("Error doing select, I'm gettin' outta here\n"); }> return; }> } }> if (nfds == 0) }> continue; /* timer expired */ }> read (0, &c, 1); /* the sucker hit a key */ } ^^^^^^^^^^ } Another mood point. this should be - } read(fileno(stdout),&c,sizeof(char)); Right again. I really do code more portably now (honest). This code is from a program which is necessarily BSD specific (it looks at rwhod packets, which is a hack only Berkeley could love), so I went ahead and harcoded those fd values, a habit I've mostly broken now. I could argue about sizeof(char), in that I want to only read one byte, even if sizeof(char) wasn't 1, but it's not worth it. } And if you are overly cautious } } if ((readval = read(fileno(stdout),&c,sizeof(char))) == -1) } perror("read failed"); } else if (readval == 0) } fprintf(stderr,"EOF encounter\n"); I wasn't overcautious, I wanted to quit on the slightest excuse and leave. If there was a read error or EOF, I'd exit through the switch statement, though I should have cleared the character before reading. }> switch (c) { }> case 'r': }> case 'R': }> case 0x12: /* ^R */ }> case 'l': }> case 'L': }> case 0x0C: /* ^L */ }> (void) wclear (stdscr); /* clear the physical screen */ }> (void) wrefresh (stdscr);/* for reassuring feedback */ }> break; }> default: }> return; }> } }> } }> } } Eddie Wyatt }e-mail: edw@ius1.cs.cmu.edu I'm a little embarrassed by the number of nits to be picked in my sample code, I should have cleaned it up before posting. But anyway, I'm still a fan of select, when used appropriately it can greatly simplify your life, and achieving the same functionality without it is a major pain. Ron Hitchens hitchens@ut-sally.uucp hitchens@godzilla.cs.utexas.edu