Plan 9 from Bell Labs’s /usr/web/sources/contrib/mycroftiv/root/sys/man/1/io

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


.TH IO 1 
.SH NAME
io, iosrv, ioshell  \- persistent multiplexed i/o sessions, or 'screen without a screen'
.SH SYNOPSIS
.B io
[
.B -a -i -p -v
]
[
-l
.I logfile
]
[
.B -c
.I cmd
]
.I srvname
.PP
.B io
.I srvname
[
.B zap 
.B slow 
.B fast
.B here
]
.PP
.B iosrv
[
.B -hrspv
]
[ 
.B -t sleeptime
]
.I srvname
.PP
.B ioshell
.I filefromfd0 filetofd1 filetofd2 ctlfile
.PP
.SH DESCRIPTION
.I Io
invokes 
.IR iosrv (1)
to create a system of 
.IR pipe (3)
devices available as a 
.IR srvfs (4)
and starts an 
.IR rc (1)
shell with its file descriptors redirected to these pipes, then uses 
.IR ioshell (1)
as a client for these connections. The overall usage model is somewhat similar to GNU 
.I screen
but without the additional complexities of TTY management.
.PP
The base behavior of 
.IR io (1)
.I srvname
is bimodal, and will function as either a client or server depending on whether 
.B /srv/srvname
exists. If no name is provided, 
.I io
will create or attach to a 
.B /srv
named 
.B /srv/iorc.$pid
containing a persistent 
.I rc
session. Thus, the simplest possible model of use is:
.IP
.EX
io
.EE
.PP
to start a backgrounded 
.I iosrv 
hosted persistent rc shell, and then 
.IP
.EX
io
.EE
.PP
from any window with access to that 
.B /srv
to connect to it. 
.PP
By default, no connection is made to the initially created 
.I rc.
The
.B -a
flag will connect the calling window to the 
.I rc
by simply invoking 
.I io srvname
after it has completed the 
.I iosrv
.B /srv
setup. Conversely, if the
.B -i
flag is given, the initial window is run with the 
.I iosrv
server itself foregrounded in interactive control console mode, with logging sent to the initiating window and that window's keyboard input sent to the 
.B ctl/data
file. Otherwise, the output is backgrounded and control messages can only be written via echo to the mounted 
.B ctl/data
pipe.
The
.B -v
option activates verbose debug logging of all the client and server message passing, and 
.B -l
.I logfile
redirects logging information in either mode to the specified file, or to 
.B /tmp/iolog$pid
if no filename is given.
.PP
The
.B -p
flag is used to start in 'paranoid' mode. Normally, reading processes may fill the buffers (sized to 512k in the default compile) ahead of the output clients, who catch up 'as fast as they are able'.  Paranoid mode enforces a 'one read one write' behavior. This is generally not desirable unless a slow client needs to request well over 512k data at once at maximum speed. 
.PP
The
.B -c
.I command 
option replaces the default backgrounded 
.I rc
with the command of your choice. 
.IP
.EX
io -c cat io.cat
.EE
.PP
will make 
.IR cat (1)
the active process. Subsequent commands of the form
.B io io.cat
will connect to the running backgrounded 
.I cat
process, allowing for a very simple chat-type application between multiple users. (
.B chmod 666 /srv/cat.io
by the controlling user will be necessary first.) For more complex commands a certain amount of ingenuity in string quoting may be required.
.PP
.I io
in its client role accepts no flags. When 
.B /srv/srvname
exists, 
.I io 
.I srvname
will mount the 
.B /srv
and then start an 
.I ioshell
client attached to a new set of file descriptors requested from the 
.I iosrv.
Multiple clients may connect simultaneously, and clients may disconnect and reconnect freely. The optional arguments
[
.B zap fast slow here
]
are translated into commands sent to the iosrv ctl file.
.I zap
clears the log prior to connecting. 
.I slow
and
.I fast
set the basic loop speed of the server processes. (Processes lock or block during idle, so this does not affect load, only maximum throughput and consumption of system resources during constant i/o transmission.)
.I here
creates an additional rc on the CLIENT machine attached to the current iosrv and attaches to it. In other words, this allows the client to share a persistent 
.I rc
session back to the HOST
.I iosrv
and its other clients.  An arbitrarily compiled-in maximum of 64 file descriptors can be used progressively for a single hub. 
.PP
The
.I ioshell
client provides a few features to interface with 
.I iosrv.
It is invoked automatically by 
.I io
and rarely directly by the user. Fundamentally, 
.I ioshell
simply acts to "bucket brigade" data between the user's existing shell file descriptors and the pipes managed by 
.I iosrv.
The 
.I ioshell
is basically transparent to input and output with the exception of providing a set of commands and a communication channel to the 
.I iosrv.
Some text strings are intercepted by the 
.I ioshell
and trigger special actions. In particular:
.B remote #
,
.B local #
,
.B attach #
,
.B clear
,
.B detach
,
.B hist
, and
.B hub 
.I cmdstring
are treated as follows. Note that the connection context is relevant in particular for:
.IP
.EX
remote #
.EE
.PP
which creates a new rc session on the HOST machine (the machine running the 
.I iosrv
being targeted) with 3 new Hubs activated and shifts the connection to it. # corresponds to the lowest numbered of the new Hubs. This command can only be issued when actually connected to an io session on the remote host. (This corresponds to the conventional creation of a new shell within 'screen'.) Conversely,
.IP
.EX
local #
.EE
.PP
functions similarly but the rc is hosted by the CLIENT machine (the machine importing the /srv - if both the client and the server are on the same machine, 
.B remote
and
.B local
are equivalent.) Multiple clients can all share rc sessions to the other clients via the shared iosrv. In other words, starting new shared rc's using the 
.B local
option makes iosrv the equivalent of a shared 
.B /srv
for the connected machines, where any machine can post new pipes for either input or output. Note that local will always refer to the local client machine, but the meaning of 'remote' shifts depending on where the current 
.I ioshell
is attached.
.IP
.EX
attach #
.EE
.PP
shifts to the currently existing 
.I iosrv 
.I rc
whose lowest Hub # is given. Using new and attach, the user can create additional instances of
.I rc
connected to the current 
.I iosrv
and switch between them freely. VERY IMPORTANT: as a standard 
.I rc
shell or other traditional textual input/output program uses 3 file descriptors, numbering should proceed by increments of 3 as additonal 
.I rc
are attached to a given
.I iosrv
host. Some care must be taken to track these numbers as the results of misaligned attaches could be disruptive to the integrity of the session. The simple rule is that the numeric parameter to the attach, remote, and local commands should always be a multiple of 3. 
.IP
.EX 
detach
.EE
.PP
ends the current ioshell attachment to the 
.I iosrv
pipes - it does not affect the remote system in any way, it simply returns control to the original shell. (it also requests a 
.IR fortune (1)
on the way out.)
.B clear
resets the internal buffers and pointers of the primary set of hubs (H0, H1, and H2).
.B hist
provides a command history of the user's attached
.I ioshell.
Note this is not a complete log of all attached input clients, but only of the local client. 
.B hub
.I cmdstring
sends cmdstring to the 
.I iosrv
.B ctl
file, enabling arbitrary commands to be passed to the session. Notable commands include: 
.B hub fear
to active paranoid mode and 
.B hub calm
to deactivate it. 
.B hub quit
terminates the entire iosrv and kills all reader and writer processes.
.B hub debug 
and 
.B hub shutup
act to start and stop verbose debug output respectively. (Note: the logging information is not sent to the 
.I ioshell
client, but rather to the location specified by the initial 
.I io
server command.). 
.PP
The low level hub commands are also supported. Each hub command begins with the letter 'h', is followed by a numeric Hub identifier, then a single letter representing a verb, and then usually an additional numeric parameter. The 
.I io
and
.I ioshell
tools use these commands to perform their actions.
.IP
.EX
hub h1t50
.EE
.PP
from within an attached 
.I ioshell
sets the sleeptime parameter of Hub 1 to 50 ms, which will occur twice per read cycle and at least once per write cycle. See the examples section and source code for more details. Verbs are:  t: time, c: clear, s: start, o: output. e: err, i: input, f: freefd, k: killfd x: xit, v: view, y: kill rdproc, z: kill wrproc. All commands except c, x, and v take a 4th numeric parameter. Due to ongoing development, a full specification of the 
.B 'h%d%c%d'
Hub commands will not be offered in this manpage.
.PP
The 
.I iosrv
command is usually called from the 
.I io
wrapper script. The options that vary from those of the wrapper script are mostly experimental debugging options. The
.B -dhrs
flags deactivate the default setup, turn off file descriptor preservation, turn off 
.IR ramfs (4)
and prevent a 
.B /srv
from being posted, respectively. Check the source code for details. 
.PP
In theory, there is nothing preventing the
.I iosrv
pipes from carrying any kind of data. A small amount of testing of remote control of GUI apps indicates this is a fruitful area for experimentation, and in theory multiple
.I iosrv
can be connected to create pipe topologies of arbitrary complexity involving multiple machines with the ability to connect and disconnect clients in real time.
.PP
.SH EXAMPLES
For most users and purposes, 
.B io
.I srvname
used to both start and connect to a given 
.B /srv
(in combination with any needed network imports) will be the primary mode of usage, along with
.B remote #
and
.B attach #
commands from within the attached ioshells. The concluding example of a manually created set of connections is provided to demonstrate additional possibilities for further development of the underlying 
.I iosrv
core.
.PP
Start a session named aug1 and connect to it in the same window as it was launched:
.IP
.EX
io -a aug1
.EE
.PP
Connect a second client to that session:
.IP
.EX
io aug1
.EE
.PP
Start another session named rc.2 backgrounded but with non-verbose logging written to the default logfile:
.IP
.EX
(host) io -l rc.2
.EE
.PP
Connect to that 
.I rc
session from a remote client. First, import the host machine's 
.B /srv
then connect and also clear the backscroll:
.IP
.EX
(client) import -ac HOST /srv
.EE
.PP
.IP
.EX
(client) io rc.2 zap
.EE
.PP
From within that rc, create another rc attached to the current iosrv beginning on Hub 3 (the first available):
.IP
.EX
(client io:) remote 3
.EE
.PP
connect another client and switch to that rc:
.IP
.EX
(client) io rc.2
.EE
.PP
.IP
.EX
(client io:) attach 3
.EE
.PP
switch back to the original rc:
.IP
.EX
(client io:) attach 0
.EE
.PP
share an rc from the client machine back to the iosrv:
.IP
.EX
(client io:) local 6
.EE
.PP
from inside a connected HOST machine 
.I ioshell
connect to the new rc hosted by the client:
.IP
.EX
(host io:) attach 6
.EE
.PP
The above series of commands demonstrates the basic principle of referring to multiple rc sessions within a single 
.I iosrv
is that the numbering proceeds by threes, because each 
.I rc 
makes use of a set of the three standard file descriptors, each of which uses one Hub. Leaving Hubs unused in between rc trihub groupings is harmless apart from inefficiency, but overlapping multiple trihubs within the same numeric grouping will produce results that are either broken or awesomely nonconventional depending on the user's perspective.
.PP
Create an 
.I iosrv
that allows you to monitor dns requests:
.IP
.EX
io -c 'tail -f /sys/log/dns' io.dns
.EE
.PP
The following examples demonstrate some of the internal control interface.
.PP
Start an 
.I iosrv
with verbose logging and a local control console, and issue several commands to it:
.IP
.EX
io -i -v rc.3
.EE
.PP
.IP
.EX
fear (set paranoid mode)
.EE
.PP
.IP
.EX
h1v (view info on hub 1)
.EE
.PP
.IP
.EX
shutup (turn off debugging-level output)
.EE
.PP
Now connect a shell to the session with no io delay and issue 'hub' commands to create a new set of usable multiplexed io pipes:
.IP
.EX
io rc.3 fast (since paranoid mode was set, use 'fast')
.IP
.EX
hub h3s3 (start new hub 3 with H3in3 as initial input)
.EE
.PP
.IP
.EX
hub h3o3 (add an output file H3out3 from Hub 3)
.EE
.PP
.IP
.EX
hub h4s4
.EE
.PP
.IP
.EX
hub h404 (similarly for Hub 4)
.PP
.IP
.EX
hub h5s5
.EE
.PP
.IP
.EX
hub h5e5 (Hub 5 names output H5err5 for mnemonic)
.EE
.PP
Now open a new window and connect a new 
.I rc
to the new hubs:
.IP
.EX
mount -c /srv/rc.3 /n/rc.3 && cd /n/rc.3
.EE
.PP
.IP
.EX
rc -i <H3out3/data1 >H4in4/data >[2]H5in5/data &
.EE
.PP
And finally connect to that persistent 
.I rc
from a new client:
.IP
.EX
mount -c /srv/rc.3 /n/rc.3 && cd /n/rc.3
.EE
.PP
.IP
.EX
ioshell H3in3/data H4out4/data1 H5err5/data1 ctl/data
.EE
.PP
(Note that identical results could be obtained by issuing the commands above directly to the control console similarly to the first group of control commands shown.)
.PP
.SH SOURCE
.B sources/contrib/mycroftiv/iosrv.tgz
.SH "SEE ALSO"
UNIX pipes,
.IR pipe (3)
,
.IR srv (3)
and
.IR aux/consolefs (4)
.SH BUGS
Not all flags are sane in combination. The command parser is primitive. Not all user initiated control actions are error checked. There are no provided options for giving clients different levels of privilege to control the session. Mental incapacity to grapple with the combinatoric possibilities of higher-dimensional pipe topologies (see below). Large amount of client connections and disconnections will produce many processes that may need manual pruning. Some of the semantics are ad-hoc and users should be provided with more naming and numbering control. Reinvention of the wheel in octagonal form. Parameters such as data bucket size are compiled-in. The whole thing should probably implement itself as a 9p fs rather than piggybacking on 
.I exportfs
(4) and 
.I pipe
(3) files.
.PP
-
.PP
"Doug had for years and years, and he talked to us continually about it, a notion of interconnecting computers in grids, and arrays, very complex, and there were always problems in his proposals. That what you would type would be linear and what he wanted was three-dimensional, n-dimensional...I mean he wanted just topological connection of programs and to build programs with loops and and horrid things. He had such grandiose ideas and we were saying, the complexity you're generating just can't be fathomed. You don't sit down and you don't type these kind of connections together. And he persisted with the grandiose ideas where you get into Kirchoff's law problems...what happens if you have a feedback loop and every program doubles the number of characters, it reads one and writes two? It's got to go somewhere - synchronization - there's just no way to implement his ideas and we kept trying to pare him down and weed him down and get something useful and distill it. What was needed, was real ideas...and there were constant discussions all through this period, and it hit just one night, it just hit, and they went in instantly."
.PP
.I ~Ken Thompson on UNIX pipes' origins
.PP
.B http://www.princeton.edu/~hos/mike/transcripts/thompson.htm

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].