jpayne@cs.rochester.edu (Jonathan Payne) (05/17/88)
Hi. The simple version of my question is, is there an equivalent function in SysV for BSD's select()? If the answer is no, here's what I am trying to do. I want to get input from either the keyboard or from some other file description. I don't want to sit around polling the two, because that would be ridiculous. Is there any reasonable way to do that on SysV? (Actually, the question should be, is there anyway to do that on non-bsd systems?) Thanks for any suggestions. Jonathan Payne
ekrell@hector.UUCP (Eduardo Krell) (05/17/88)
In article <9738@sol.ARPA> jpayne@rochester.UUCP writes: >Hi. The simple version of my question is, is there an equivalent >function in SysV for BSD's select()? The simple version of my answer is NO. >If the answer is no, here's what I am trying to do. I want to get input >from either the keyboard or from some other file description. System V Release 3 and up have a poll() system call which acts like select(), but works only on stream file descriptors. Currently, the tty driver is not streams-based (it will be in the future), so poll() won't help you either. Eduardo Krell AT&T Bell Laboratories, Murray Hill, NJ UUCP: {ihnp4,ucbvax}!ulysses!ekrell ARPA: ekrell@ulysses.att.com
gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/17/88)
In article <9738@sol.ARPA> jpayne@cs.rochester.edu (Jonathan Payne) writes: >I want to get input >from either the keyboard or from some other file description. I don't >want to sit around polling the two, because that would be ridiculous. If you set MIN and TIME to 0 in the terminal handler, then an attempt to read from the terminal with no data available will return immediately. There is nothing analogous for ordinary files.
tim@amdcad.AMD.COM (Tim Olson) (05/17/88)
In article <10293@ulysses.homer.nj.att.com> ekrell@hector (Eduardo Krell) writes: | In article <9738@sol.ARPA> jpayne@rochester.UUCP writes: | | >Hi. The simple version of my question is, is there an equivalent | >function in SysV for BSD's select()? | | The simple version of my answer is NO. | | >If the answer is no, here's what I am trying to do. I want to get input | >from either the keyboard or from some other file description. | | System V Release 3 and up have a poll() system call which acts like | select(), but works only on stream file descriptors. Currently, the | tty driver is not streams-based (it will be in the future), so poll() | won't help you either. | The only way I have found to do this kind of thing under SYSV is to restructure the program to have a child process dedicated for each fd of the select(), and have them communicate through shared memory, or perhaps named pipes. -- Tim Olson Advanced Micro Devices (tim@amdcad.amd.com)
jds@mimsy.UUCP (James DaSilva) (05/17/88)
In article <7904@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn) writes: >In article <9738@sol.ARPA> jpayne@cs.rochester.edu (Jonathan Payne) writes: >>I want to get input >>from either the keyboard or from some other file description. I don't >>want to sit around polling the two, because that would be ridiculous. > >If you set MIN and TIME to 0 in the terminal handler, then an attempt >to read from the terminal with no data available will return immediately. >There is nothing analogous for ordinary files. That's just his point, Doug. Sure, once you call ioctl to set things up to return immediately if no data is present, the polling loop looks something like this: for(;;) { if(size1 = read(fd1,buffer1,MAX)) do_something_with(buffer1,size1); if(size2 = read(fd2,buffer2,MAX)) do_something_with(buffer2,size2); } (Ignore the fact that this simple example doesn't handle error returns from read. You get the point). This REALLY eats CPU time. If nothing is pending, it will use as much CPU as the kernel is willing to give it. Not very friendly. The natural way to handle this in System V is to use two processes, each of which is waiting on one file descriptor. You can then use shared memory and/or signals, semaphores or message queues to get the data around, to taste. - Jaime ---------------------------------------------------------------------- usenet: uunet!mimsy!jds James da Silva internet: jds@cs.umd.edu "Stand on each other's shoulders, not on each other's toes."
charles@c3engr.UUCP (Charles Green) (05/21/88)
In article <11536@mimsy.UUCP> jds@mimsy.umd.edu (James da Silva) writes: >>In article <9738@sol.ARPA> jpayne@cs.rochester.edu (Jonathan Payne) writes: >>>I want to get input >>>from either the keyboard or from some other file description. I don't >>>want to sit around polling the two, because that would be ridiculous. >The natural way to handle this in System V is to use two processes, each of >which is waiting on one file descriptor. You can then use shared memory >and/or signals, semaphores or message queues to get the data around, to taste. My favorite solution is to have several small "multiplexor" processes, all identical but exec()ed with a unique numeric argument, reading their respective stdins and all writing into the same pipe that's read by the main process. When one of the multiplexor processes completes a read(), he does a single write() to the pipe containing his unique ID, a byte count, and the data. The main process sleeps on a read() of the pipe of a size sufficient to pick up the "header" (ID and byte count). When he gets one, he issues another read() to pick up the data. This scheme works because a write() to a pipe is atomic; data from the other multiplexor processes won't be interspersed with it (as opposed to TTYs...) However, you have to be able to accept data from all "channels" simultaneously; you can't selectively read data from one channel and not another. fd >----> [mux] >-- \ fd >----> [mux] >---+--> (pipe) >--> [main process] / fd >----> [mux] >-- -- #ident "@(#).signature 1.5 :~charles/s..signature 04/27/88 21:40:43" charles@c3pe.UUCP charles_green%c3gate@c3pe
csch@tmpmbx.UUCP (Clemens Schrimpe) (05/22/88)
jpayne@cs.rochester.edu (Jonathan Payne) writes: {} {} Hi. The simple version of my question is, is there an equivalent {} function in SysV for BSD's select()? {} {} If the answer is no, here's what I am trying to do. I want to get input {} from either the keyboard or from some other file description. I don't {} want to sit around polling the two, because that would be ridiculous. Is {} there any reasonable way to do that on SysV? (Actually, the question {} should be, is there anyway to do that on non-bsd systems?) 1) The answer is NO :-( 2) The answer is YES :-) There is a way to work around that problem - but not unless you are willing to hack your kernel. One possible way is to build a device-driver, if you don't have tha capability to hack the list of system calls. OK: Here're my thoughts: Reduced to the main problem, the thing you'd like to know is, whether a read/write on a filedescriptor will block or not. Having a way to determine this, you can write a simple loop in the kernel checking this for each fd requested and if nothing happened, goto sleep by either using delay() or timeout(), sleep(), wakeup(). /* arg contains a bitmask as in BSD-select(2) */ for (;;) { mask = 0; for (fd=0; fd < 8*sizeof(arg); ++fd) { if ( !(arg & (1<<fd))) continue; if (check(fd)) mask |= 1<<fd; } if (mask) return(mask); delay(Hz/10); /* 1/10 sec idle */ } OK - now: how to determine, if there is data available on a fd; Having the fd, you can step into the list in the user-structure named u.u_ofile[], which is of type filep_t. In the file-structure you'll find a pointer to the related inode-structure. OK - if you have this, you can now determine the TYPE of the file: - An ordinary file is always read/writeable - mark this fd! - A named pipe is readable, if it's size stated in the inode-structure is >0 and writeable if it's size is less then than the maximum size of a named pipe (10240 on Xenix ???). - A character-device is more difficult: *** The facts stated from hereon in the posting refer to the behavior *** of SCO Xenix 2.2 and are not neccessarily compatible with SYS V! The device, to which the fd belongs to could be found out by getting the major and minor device numbers out of the first to bytes in the block-list of the above named inode-structure. Having the major device number you can look up the array of tty-structures from the cdevsw[] table. Now you index that array with the minor device number and finally get the tty-structure. (Uff :-) Having this you can look, how many bytes are pending in the in/output queues and decide, what to do. NOTE: This is no fun - even if you have device drivers, indexing their tty-structures not with the minor device number. And that's mostly the case, where higher bits the minor-# state the type of device being used. If you only want to know about the availability of data on the controlling tty, you should refer to the related tty-structre via the pointer provided in the user-structure named u.u_ttyp! Not an easy way - isn't it ???? ]:-} AGAIN: These are only thoughts - I tried all this and it all works on SCO, but I never (!!!) made a complete select() out of this. So all the stuff was only used fragmentarily. For those of you reading this article in comp.unix.wizards: please respond to me via email, because comp.unix.wizards is often too full for me so I skip many articles ... Clemens Schrimpe, netmbx GbR (Berlin, West-Germany) UUCP: csch@tmpmbx = Europe: ...!unido!tmpmbx!csch, USA: ...!pyramid!tmpmbx!csch BITNET: csch@db0tui6 csch@tub.BITNET PHONE: +49-30-332 40 15 FAX: +49-30-361 40 93 TELEX: (066)+186672 net d BTX: 0303325016-0003 MODEM: +49-30-332 50 16 (V.22/V.22bis), +49-30-331 30 76/40 72 (V.21) Username: gast X.25: not stated herein (too many hackers around :-)
allbery@ncoast.UUCP (Brandon S. Allbery) (05/25/88)
As quoted from <7904@brl-smoke.ARPA> by gwyn@brl-smoke.ARPA (Doug Gwyn ): +--------------- | In article <9738@sol.ARPA> jpayne@cs.rochester.edu (Jonathan Payne) writes: | >I want to get input | >from either the keyboard or from some other file description. I don't | >want to sit around polling the two, because that would be ridiculous. | | If you set MIN and TIME to 0 in the terminal handler, then an attempt | to read from the terminal with no data available will return immediately. | There is nothing analogous for ordinary files. +--------------- But that still leaves him polling. Jon: It's a bit ironic; the closest thing to a solution is something I've been planning to do to "portsrv" in the Jove distribution. Have your files opened by subprocesses: one process per file. They should communicate with the parent process via a message queue. Each does blocking reads; when the read succeeds, the process should package it up in a message with an ID field unique to the file/process (you can use dev/inode, process ID, or anything else you choose as long as it's unique to each process). The parent program then does a blocking msgrcv on the message queue. When a message comes in, the parent can examine the ID field to determine which file it got the data from, and process it as appropriate. If another message comes in while the parent is processing, it will remain on the queue until the parent gets around to issuing another msgrcv. This is, alas, restricted to System V (I can think of some places where it'd be useful on ncoast, but ncoast is System III). There is *no* general solution for System III, Xenix 3 or V7. (You *could* use a FIFO to fake a message queue under System III/Xenix 3, but now you're getting into nasty complications. And it's far easier to set up a two-way message queue than it is to coordinate multiple FIFOs in a two-way connection, if you need it. And FIFOs still aren't in pre-System III *nixes.) -- Brandon S. Allbery, moderator of comp.sources.misc {well!hoptoad,uunet!marque,cbosgd,sun!mandrill}!ncoast!allbery Delphi: ALLBERY MCI Mail: BALLBERY
gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/25/88)
In article <7812@ncoast.UUCP> allbery@ncoast.UUCP (Brandon S. Allbery) writes: >| If you set MIN and TIME to 0 in the terminal handler, then an attempt >But that still leaves him polling. Look, this is JOVE we're talking about, for Chrissakes! The needed functionality is to "peek" to see if there is keyboard input every so often while in the middle of a screen update loop, so unnecessary screen output can be avoided. The solution I gave works just fine for that. All these more complex schemes people have been proposing are far less efficient.
ckl@uwbln.UUCP (Christoph Kuenkel) (05/26/88)
> jpayne@cs.rochester.edu (Jonathan Payne) writes: > {} > {} Hi. The simple version of my question is, is there an equivalent > {} function in SysV for BSD's select()? > {} If the answer is no, here's what I am trying to do. I want to get input > {} from either the keyboard or from some other file description. I don't > {} want to sit around polling the two, because that would be ridiculous. Is > {} there any reasonable way to do that on SysV? A blocking syscall blocks a process. so, if you like to wait for several events at the same time, you need several processes. a solution to your problem would be to fork off a watchdog that reads the keyboard and signals his daddy when input arrives. the parent may then collect what had been read using system V ipc (msges, fifos or whatever). this works quite good unless interrupted system call are a problem. also note that signals may get lost in system 5 (upto rel 2). if your have several input sources, you should setup a watchdog for any source and establish something like a protocol between the watchdogs and the main process. the watchdogs would then send requests to the main proc containing the data received. the main process would block on a single input queue only. if tty input is the most interesting thing, you should modify the watchdog so that it only reads from the tty when requested by the main process. the main process would do a time-out read from the tty and accept watchdog input only if a time-out occured.
alvitar@madhat.UUCP (Phil Harbison) (05/27/88)
In article <2643@c3engr.UUCP>, charles@c3engr.UUCP (Charles Green) writes: > > My favorite solution is to have several small "multiplexor" processes, > all identical but exec()ed with a unique numeric argument, reading their > respective stdins ... When one of the multiplexor processes completes a > read(), he does a single write() to the pipe containing his unique ID, > a byte count, and the data. > I use a similar approach on my version of emacs to implement subprocesses running in emacs windows. It is a major win on the Sys5 version since the previous approach used lots of CPU time doing NODELAY reads on the keyboard and childs stdout pipe. Another big win is I only have one version of the code that runs on v7, BSD, and USG flavors of UNIX. A nice side effect is that polling the keyboard is simple, since I can do an fstat to discover how much data is in the IPC pipe. If anyone wants example code, drop me a note in the mail. -- Live: Phil Harbison USPS: 3409 Grassfort Drive, Huntsville, AL 35805-5421 UUCP: clyde!madhat!alvitar PSTN: 205-881-4317 or 205-830-4310x210