[comp.os.minix] Job control?

creps@silver.bacs.indiana.edu (Steve Creps) (01/31/88)

   I've just started checking out Minix, and have a question on
job control. Namely, how much is supported? In Ultrix I can run
a job, type ^Z to suspend it, then type fg or bg to restart it
running in foreground or background. Does Minix support anything
like this? If the supplied shell doesn't do this, would it still
be possible to write another shell that does?

-	-	-	-	-	-	-	-	-
Steve Creps on the VAX 8650 running Ultrix 2.0-1 at Indiana University.
creps@silver.bacs.indiana.edu, ...iuvax!silver!creps, creps@iubacs.bitnet
"F-14 Tomcat! There IS no substitute."

paradis@encore.UUCP (Jim Paradis) (02/01/88)

In article <712@silver.bacs.indiana.edu> creps@silver.UUCP (Steve Creps) writes:
>   I've just started checking out Minix, and have a question on
>job control. Namely, how much is supported? In Ultrix I can run
>a job, type ^Z to suspend it, then type fg or bg to restart it
>running in foreground or background. Does Minix support anything
>like this? If the supplied shell doesn't do this, would it still
>be possible to write another shell that does?

Sorry, but job-control currently does not exist in MINIX, and it would
be non-trivial to add support.  I plan to do this someday (I even have
hooks in my TTY driver for its eventual support), but I have no idea 
exactly when.  Off the top of my head, if you wanted to support job 
control you would have to AT LEAST do the following:

	(1) Add support for stopping processes.  This involves
	    adding a new process state (STOPPED) and modifying
	    the scheduler to know not to activate such processes.

	(2) Add support for the equivalent of the wait3() system call.

	(3) Modify the shell (or preferably write a C-shell clone) to
	    take advantage of the new support.

   +----------------+  Jim Paradis                  linus--+
+--+-------------+  |  Encore Computer Corp.       necntc--|
|  | E N C O R E |  |  257 Cedar Hill St.           ihnp4--+-encore!paradis
|  +-------------+--+  Marlboro MA 01752           decvax--|
+----------------+     (617) 460-0500             talcott--+
...coated with sesame seeds, and garnished with lark's vomit!

dm@socrates.bbn.com (David Mankins) (02/02/88)

> Sorry, but job-control currently does not exist in MINIX, and it would
> be non-trivial to add support.  I plan to do this someday (I even have
> hooks in my TTY driver for its eventual support), but I have no idea 
> exactly when.  Off the top of my head, if you wanted to support job 
> control you would have to AT LEAST do the following:
> 
>         (1) Add support for stopping processes.  This involves
>             adding a new process state (STOPPED) and modifying
>             the scheduler to know not to activate such processes.
> 
>         (2) Add support for the equivalent of the wait3() system call.
> 
>         (3) Modify the shell (or preferably write a C-shell clone) to
>             take advantage of the new support.


A few years ago, a friend of mine and I implemented a facility very
similar to job control in our V7 kernel (running on a very obscure bit
of hardware), which had none of these disadvantages, and required a
tiny change to the tty driver, and a simple window manager/job
controller.  The result was actually superior (in some ways) to
Berkeley job control (no programs had to be changed to work with it,
programs which don't do i/o don't EVER get blocked).
 
The point of our job control was not to suspend a process, really, but
to prevent the output of a program from splatting on the terminal
while you were working with some other program.  What we were REALLY
doing was implementing a window manager system that didn't require
PTYs.  I/O was permitted by process-groups.

I shall describe our window manager implementation, the simplification
of turning it into job control is trivial.

The things we did to UNIX are documented in:

   Franklin & Mankins, ``A simple window management facility for the UNIX
      timesharing system'', _USENIX Summer 1983 Toronto Conference
      Proceedings_. 

Unfortunately, the paper as reprinted in the proceedings is missing
one of its early pages.  I no longer have the paper in electronic
form, or I would offer to send it to folks.  I will send a Xerox copy
to you, Mr. Paradis, since your terminal driver seems to be all the
rage.  I don't have MINIX (nor even a MINIXable PC) myself.

We were doing a window manager for a terminal which was able to
restrict output to rectangular regions, and which could save part of a
region in a rectangular region of the screen (the BBN Bitgraph).  A
less-interesting version was possible for VT100s, with their
scrolling-region commands, and I also once wrote a job-controller that
used the same mechanism to work on dumb terminals.

The basic idea was: there was a process to which the kernel would send
a signal when the user typed a ^Z.  This process would read the
current tty modes and save them, then would interpret user commands to
change to another window, would tell the terminal to switch to the new
window's region, and would restore the new window's terminal modes.

We added the following UNIX calls:

set_tty_manager(tty_fd)
	Make the current process the terminal manager, if one has not
	already been assigned (this was an IOCTL, ``TIOCSMAN'').

get_tty_manager(tty_fd) returns process-id
	Find out the terminal manager's process id (-1 if there's no
	window manager).  Another IOCTL, ``TIOGMAN''.

relinquish_tty_managerhood()
	Undo a set_tty_manager.  IOCTL TIOCRMAN.

setpgrp(proc_id, pgroup)
getpgrp(proc_id) returns pgroup
	Set and get the process group for process proc_id. 

set_tty_pgroup(tty_fd, pgroup)
get_tty_pgroup(tty_fd) returns pgroup
	set and get the process group for the terminal (implemented as
	two ioctl calls, TIOCSPGRP and TIOCGPGRP.

get_blocked_process(tty_fd, &gbp_struct)
	Fill in the gbp_struct with a process id, the process's
	pgroup, and the reason the process is blocked (TTY_INPUT --
	the process tried to do a read on the terminal; TTY_OUTPUT --
	the process tried to do a write to the terminal; and TTY_IOCTL
	-- the process tried to do an IOCTL on the terminal.  This
	routine returns -1 when the calling process is not the
	terminal's window manager, and it BLOCKS if there are no more
	blocked processes to handle.

killpg(pgroup, signal)
	send the indicated signal to all processes in the specified
	process group.

We also added three new mode bits, a new signalling character (the
moral equivalent of BSD job control's ^Z), and an ioctl, TIOCSTUFF, to
allow stuffing characters into a process's terminal input queue.  In
addition, our UNIX had a means of telling whether a read on the
terminal would block.  I don't know if MINIX has such a thing.

The mode bits:

TL_PGROUPIO: enables the whole package -- a process that is not in the
	TTY's process group will be block at an attempt to read,
	write, or ioctl.  All tty-related ioctls will block (if the
	process's process-group isn't the same as the tty), even
	those that only inquire of the terminal modes without changing
	them, because a program would get confused if it reads the
	terminal modes associated with, for example a screen editor.

TL_DEFINPUT: holds up the user's typing.  When it is set, further
	typein by the user is not processed, but is held in a special
	queue until TL_DEFINPUT is turned off.  At that time the
	contents of the queue are fed to the rest of the terminal
	driver as though they had just been typed.

	TL_DEFINPUT is necessary principally during the change from
	one window to another, when the terminal modes (or the region
	state in a window manager) may be incorrect.

TL_BLREAD: is like TL_DEFINPUT but on the other side of the input
	queue.  It blocks all terminal reads, even those performed by
	processes in the current process-group.  This bit is not
	necessary for job control, but is useful if you're
	implementing a window manager.  What this bit does is it
	allows OUTPUT to the terminal without permitting input.  The
	scenario is this:

		you're interacting with rogue in window A
		the compilation in window B tries to write to the
		  terminal, but blocks.
		the kernel returns to the window manager, which was
		  blocked in a get_blocked_process() call.
		the window manager restores window B's terminal modes,
		  switches the terminal to window B
		  sets the tty to window B's process-group,
		the compiler's write takes place in window B

	While window B is active, what the user types on the keyboard
	wants to go unprocessed by the tty driver, because the user
	thinks s/he is typing at rogue.

Okay, with TL_PGROUPIO enabled and a terminal manager (or
job-controller) assigned via set_tty_manager(), the user wants a way
of talking to the window manager: enter the job-control character.
The user types ^Z, the kernel does:

	1) sends a new signal, SIGATTN to the window manager
	2) changes the process group of the terminal to that of the
	window manager
	3) turns on TL_DEFINPUT mode.

These three actions are combined to allow typeahead and
responsiveness.  The user may type ^Z and follow it immediately with a
window manager command (e.g., switch to a window, make a new window,
etc.).  These commands should not be read by the process in the
current window, nor should they be echoed in that window (TL_DEFINPUT
prevents that).

The effect of ^Z is in effect EVEN IN RAW MODE.  We took this drastic
step because we wanted a uniform interface.  We didn't want to change
every raw-mode program to know about this.  To send a ^Z to a program,
the user types two of them, and the window manager uses TIOCSTUFF to
stuff the character into the input buffer of the current window.

TIOCSTUFF and the is_there_input() call are used to allow other forms
of typeahead.  When the user types ^Z, there may be unprocessed
characters in a window's input queue.  The window manager uses
is_there_input() to drain the tty input buffer (without blocking in a
read) and will later use TIOCSTUFF to shove the characters into the current
window's input queue when the user returns to this window.

The paper gives a thorough discussion of the changes to the UNIX tty
driver and also outlines the implementation of the window manager
(down to the level of pseudo-code).

Well, despite 8500 characters worth of exposition, it really was a
simple change to the kernel (the window manager was a little hairy,
the job controller was trivial).

I THINK this method could be used to implement a multi-window
environment for MINIX without the headaches of implementing full-blown
virtual terminals, but I'm not sure.

Only 365 days of America Held Hostage remain!
dave mankins