mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-11-01 02:04:32 +00:00
b6e3bbc037
- initial checkin Makefile: - changes to allow for the new gsh ref manual - moved *.Z *.gz files into an "uploads" subdir README: - added some comments re the sgml stuff head.html, index.html, mkmandex, mkhtmlman, manindex.html, mkstatus, oldrefs.html, refs.html, tail.html: - eliminated <base> tags - fully specify page colours refs.html: - added links for new gsh manual index.html: - add dates for "NEW" section - added comment about new gsh manual intro.tex: - fully specify page colours - fixed a typo: "2.0.4" --> "2.0.6" in installation notes kern.tex: - fully specify page colours
2702 lines
95 KiB
TeX
2702 lines
95 KiB
TeX
%
|
|
% GNO Kernel Reference Manual
|
|
%
|
|
% $Id: kern.tex,v 1.6 1999/02/21 23:37:12 gdr-ftp Exp $
|
|
%
|
|
|
|
\documentclass{report}
|
|
\usepackage{html}
|
|
\usepackage{makeidx}
|
|
\makeindex
|
|
\bodytext{
|
|
bgcolor=#ffffff
|
|
textcolor=#000000
|
|
linkcolor=#0000FF
|
|
vlinkcolor=#001177
|
|
alinkcolor=#001177
|
|
}
|
|
\begin{document}
|
|
|
|
\title{GNO Kernel Reference Manual}
|
|
\author{By Jawaid Bazyar \\ Edited by Andrew Roughan and Devin Reade}
|
|
\date{19 November 1997}
|
|
\maketitle
|
|
|
|
\begin{latexonly}
|
|
\tableofcontents
|
|
\end{latexonly}
|
|
|
|
\parindent=0pt
|
|
\parskip=1pc
|
|
|
|
%
|
|
% CHAPTER: Introduction
|
|
%
|
|
|
|
\begin{latexonly}
|
|
\chapter{Introduction}
|
|
\end{latexonly}
|
|
\begin{htmlonly}
|
|
\chapter{Chapter 1: Introduction}
|
|
\end{htmlonly}
|
|
|
|
The GNO kernel is the heart of the GNO Multitasking Environment
|
|
(GNO/ME). The GNO kernel provides a
|
|
layer of communication between the shell (and shell-based
|
|
programs) and the operating system, GS/OS. The kernel handles
|
|
such things as multitasking,
|
|
\index{background}
|
|
background processes, foreground
|
|
processes and many other features that were not previously
|
|
available on the Apple IIGS. It is these features which make
|
|
GNO/ME very powerful.
|
|
|
|
This reference manual is highly technical
|
|
in nature and is provided to help programmers develop utilities
|
|
for the GNO Multitasking Environment. The beginner has no need to
|
|
read this manual and is certainly not expected to understand its
|
|
contents. However, Chapter 5 \bf Process Management \rm and
|
|
Chapter 6 \bf Interprocess Communication \rm provide a good
|
|
background discussion for anyone who is interested in the
|
|
internal workings of the kernel.
|
|
|
|
%
|
|
% CHAPTER: GNO Compliance
|
|
%
|
|
|
|
\begin{latexonly}
|
|
\chapter{GNO Compliance}
|
|
\end{latexonly}
|
|
\begin{htmlonly}
|
|
\chapter{Chapter 2: GNO Compliance}
|
|
\end{htmlonly}
|
|
|
|
For a program to work effectively under
|
|
GNO/ME, certain rules must be followed. Most of these rules boil
|
|
down to one underlying concept ---
|
|
\bf never directly access features of the machine\rm .
|
|
Always use GS/OS, the ToolBox, or
|
|
GNO/ME to accomplish what you need. We have taken great care to
|
|
provide the sorts of services you might need, such as checking
|
|
for input without having to wait for it. GNO/ME compliance isn't
|
|
just a matter of trying to make applications work well under the
|
|
environment; it ensures that those applications stay compatible,
|
|
no matter what changes the system goes through. Below are
|
|
summarized the points you must consider when you're writing a
|
|
GNO/ME compliant application.
|
|
|
|
\section{Detecting the GNO Environment}
|
|
|
|
If your application requires the GNO Kernel
|
|
to be active (if it makes any kernel calls), you can make sure of
|
|
this by making a \bf kernStatus \rm call at the beginning of your
|
|
program. The call will return no error if the kernel is active,
|
|
or it will return an error code of \$0001 (Tool locator --- tool not
|
|
found), in which case the value returned will be invalid. The
|
|
call actually returns a 1 if no error occurs, but the value
|
|
returned will be indeterminate if the kernel is not active, so
|
|
you should only check for an error (the function
|
|
\index{toolerror} \bf toolerror\rm (3) or the variable
|
|
\index{\_{}toolErr} \bf \_{}toolErr \rm in C,
|
|
\index{assembly language programs}
|
|
the value in the A register in assembly).
|
|
|
|
You can also determine the current version
|
|
of the GNO Kernel by making the \bf kernVersion \rm call. The
|
|
format of the version number returned is the same as the standard
|
|
ToolBox calls. For example a return value of \$0201 indicates a
|
|
version of 2.1.
|
|
|
|
\bf kernStatus \rm and \bf kernVersion \rm
|
|
are defined in the \tt <gno/gno.h> \rm
|
|
header file.
|
|
|
|
\section{Terminal I/O}
|
|
|
|
The Apple II has always been lacking in
|
|
standardized methods for reading keyboard input and controlling
|
|
the text screen. This problem was compounded when Apple stopped
|
|
supporting the TextTools in favor of the GS/OS
|
|
\index{driver!console} console driver.
|
|
The console driver has a number of problems that prevent it from
|
|
being a good solution under GNO/ME. There is high overhead
|
|
involved in using it. It is generally accessed like a regular
|
|
file, which means any I/O on it must filter through several
|
|
layers before being handled. Even though in System 6.0.1 there is
|
|
a provision for patching the low-level routines the special
|
|
high-level user input features of the driver cannot be used over
|
|
a modem or in a desktop program. And GS/OS must be called to
|
|
access it, which means that while a console driver access is
|
|
occurring, no other processes can execute. See Chapter 3 \bf Mutual
|
|
Exclusion in GS/OS and ToolBox calls\rm .
|
|
|
|
GNO/ME ignores the GS/OS
|
|
\index{.CONSOLE}
|
|
\tt .CONSOLE \rm driver and replaces
|
|
the TextTools with a high performance, very flexible
|
|
generic terminal control system. GNO/ME directly supports the
|
|
console (keyboard and screen), as well as the serial ports, as
|
|
terminals. In order for a user program to take advantage of these
|
|
features and to be GNO/ME compliant, you must do terminal I/O
|
|
only through the TextTools, or through stdin, stdout, and stderr
|
|
(refNums 1,2, and 3 initially) via GS/OS. By its very nature
|
|
TextTools is slow, so we recommend using them only for small and
|
|
simple tasks. Calls to the GS/OS console driver will not crash
|
|
the system, but they will make other processes stop until the
|
|
call is completed.
|
|
|
|
You must not get input directly from the
|
|
keyboard latch (memory location \$E0/C000,
|
|
nor may you write directly to the screen memory.
|
|
GNO/ME's terminal I/O system has been designed so you don't have
|
|
to do either of these things. If you need to check for keyboard
|
|
input without stopping your application, you can make the
|
|
appropriate \bf ioctl\rm(2) call to do what you need.
|
|
|
|
In the future, GNO/ME may provide a
|
|
GNO/ME-friendly version of the GS/OS
|
|
\index{.CONSOLE}
|
|
\tt .CONSOLE \rm driver.
|
|
|
|
\section{Stack Usage}
|
|
|
|
Stack space is at a premium on the Apple IIgs. Process
|
|
stacks can only be located in \index{bank zero}
|
|
Bank 0 --- a total of 64k. This
|
|
theoretical limit doesn't apply, however, as GS/OS and other bits
|
|
of system software reserve a large chunk of this without any way
|
|
to reclaim it. There is approximately 48K of usable stack space.
|
|
This space also has to be shared with direct page space for Tools
|
|
and certain types of device drivers, however. For a program to be
|
|
GNO compliant, stack usage analysis must be done and acted upon.
|
|
Use of the stack should be minimized so that many processes can
|
|
coexist peacefully. From experience we've found that 1K usually
|
|
suffices for well-written C applications, and at a maximum 4K can
|
|
be allocated.
|
|
|
|
\index{assembly language programs}
|
|
Assembly language programs tend to be very
|
|
efficient when it comes to use of the stack. The 4K provided by
|
|
default to applications is usually more than enough for assembly
|
|
language programs. C programs can use up tremendous amounts of
|
|
stack space, especially if recursion is employed or string
|
|
manipulation is done without concern for stack usage; however,
|
|
even assembly programs can be written poorly and use a lot of
|
|
stack space. Below are some hints to keep stack usage at a
|
|
minimum.
|
|
|
|
\begin{enumerate}
|
|
\item
|
|
Avoid use of large local arrays and character strings.
|
|
Instead, dynamically allocate large structures such as
|
|
GS/OS strings with \bf malloc\rm (3) or
|
|
the Memory Manager. Alternatively, you can designate such
|
|
items as \tt ''static''\rm , which causes the C compiler to
|
|
allocate the space for the variable from main memory.
|
|
|
|
|
|
\item
|
|
Try not to use recursion unless absolutely necessary. All recursive
|
|
functions can be rewritten using standard loops and creative programming.
|
|
This is a good general programming rule because your program will run
|
|
faster because setting up stack frames is expensive in terms of
|
|
time and memory.
|
|
|
|
\item
|
|
ORCA/C 1.3 (and older) generates 8K of
|
|
stack by default, in case the desktop is started up.
|
|
Since GNO/ME compliant programs generally will not be
|
|
desktop-based, make sure you judge how much stack your
|
|
program will require and use the \tt \#pragma stacksize \rm directive
|
|
(or the \bf occ\rm (1) \bf -S \rm flag)
|
|
to limit how much stack space ORCA/C tries to
|
|
allocate for your program. Also, since ORCA/C 1.3 programs
|
|
don't use the stack given them by GNO/ME and GS/OS, when
|
|
you link your program include a small (256 bytes) stack
|
|
segment. See the utilities sources for examples of this.
|
|
ORCA/C 2.0.x (and later) allocates stack via the GS/OS supported
|
|
method, so ORCA/C 2.0 programs use exactly the amount of
|
|
stack specified by \tt \#pragma stacksize\rm .
|
|
|
|
\end{enumerate}
|
|
|
|
\section{Disk I/O}
|
|
|
|
Since the Apple IIgs doesn't have
|
|
coprocessors to manage disk access and the serial ports, either
|
|
of these requires the complete attention of the main
|
|
\index{65816 processor}
|
|
65816 processor.
|
|
This can wreak havoc in an environment with slow disks
|
|
or high-speed serial links, as accessing disks usually results in
|
|
turning off interrupts for the duration of the access. This
|
|
situation is lessened considerably with a DMA disk controller,
|
|
such as the Apple High Speed SCSI or CV Technologies RamFAST. But
|
|
this isn't as bad as it sounds; the IBM PC and Apple Macintosh
|
|
also suffer from this problem, and the solution is robust
|
|
programming. Make sure your communications protocol can handle
|
|
errors where expected data doesn't arrive quite on time, or in
|
|
full. The best solution would be an add-on card with serial ports
|
|
and an on-board processor to make sure all serial data was
|
|
received whether or not the main processor was busy (this is a
|
|
hint to some enterprising hardware hacker, by the way).
|
|
|
|
Yet another concern for GNO/ME applications
|
|
is file sharing. GS/OS provides support for file sharing, but it
|
|
is up to the application author to use it via the requestAccess
|
|
field in the \tt OpenGS \rm call.
|
|
GS/OS only allows file sharing if all current
|
|
references to a file (other instances of the file being opened)
|
|
are read-only. GNO/ME authors should use read-only access as much
|
|
as possible. For example, an editor doesn't need write permission
|
|
when it's initially reading in a file. Note that the \bf fopen\rm (3)
|
|
library routine in ORCA/C 1.2 does NOT support read-only mode
|
|
(even if you open the file with a 'r' specificier), but it does
|
|
in ORCA/C 1.3 and later.
|
|
|
|
\section{Non-Compliant Applications}
|
|
|
|
GNO/ME wasn't really designed with the
|
|
intention of making EVERY program you currently run work under
|
|
GNO/ME; that task would have been impossible. Our main goal was
|
|
to provide a UNIX-based multitasking environment; that we have
|
|
done. We made sure as many existing applications as we had time
|
|
to track and debug worked with GNO/ME. The current list of
|
|
compatible and non-compatible applications can be found in the
|
|
file ''RELEASE.NOTES'' on the GNO/ME disk.
|
|
|
|
However, due to the sheer number of
|
|
applications and authors, there are some programs that just plain
|
|
don't work; and some that mostly work, except for annoyances such
|
|
as two cursors appearing, or keyboard characters getting 'lost'.
|
|
The problem here is that some programs use their own text drivers
|
|
(since TextTools output was very slow at one time); since GNO/ME
|
|
doesn't know about these custom drivers, it goes on buffering
|
|
keyboard characters and displaying the cursor. There is a way,
|
|
however, to tell GNO/ME about these programs that break GNO/ME's
|
|
rules.
|
|
|
|
\index{auxType}
|
|
We've defined an auxType for S16 and EXE
|
|
files, to allow distinction between programs that are GNO/ME
|
|
compliant and those that are not. Setting the auxType of an
|
|
application to \$DC00 disables the interrupt driven keyboard
|
|
buffering and turns off the GNO/ME cursor. Desktop programs use
|
|
the GNO/ME keyboard I/O via the Event Manager, and thus should \em not \rm
|
|
have their auxType changed.
|
|
|
|
You can change a program's auxType with the
|
|
following shell command:
|
|
|
|
\index{chtyp}
|
|
\begin{verbatim}
|
|
chtyp -a \$DC00 filename
|
|
\end{verbatim}
|
|
|
|
where filename is the name of the
|
|
application. As more programmers become aware of GNO/ME and work
|
|
to make their software compatible with it, this will become less
|
|
of a problem, but for older applications that are unlikely to
|
|
ever change (like the America OnLine software), \$DC00 is a
|
|
reasonable approach.
|
|
|
|
%
|
|
% CHAPTER: Modifications to GS/OS
|
|
%
|
|
|
|
\begin{latexonly}
|
|
\chapter{Modifications to GS/OS}
|
|
\end{latexonly}
|
|
\begin{htmlonly}
|
|
\chapter{Chapter 3: Modifications to GS/OS}
|
|
\end{htmlonly}
|
|
|
|
The GNO system modifies the behavior of a
|
|
number of GS/OS calls in order to allow many programs to execute
|
|
concurrently, and to effect new features. The changes are done in
|
|
such a way that old software can take advantage of these new
|
|
features without modification. Following is a complete
|
|
description of all the changes made. Each section has details in
|
|
text, followed by a list of the specific GS/OS or ToolBox calls
|
|
affected.
|
|
|
|
\section{Mutual Exclusion in GS/OS and ToolBox Calls}
|
|
|
|
The Apple IIGS was not designed as a
|
|
multitasking machine, and GS/OS and the Toolbox reflect this in
|
|
their design. The most notable problem with making multitasking
|
|
work on the Apple IIgs is the use of global (common to all
|
|
processes) information, such as prefixes and direct page space
|
|
for tool sets which includes information like SANE results,
|
|
QuickDraw drawing information, etc. In most cases we've corrected
|
|
these deficiencies by keeping track of such information on a
|
|
per-process basis, that is, each process has its own copy of the
|
|
information and changes to it do not affect any other process'
|
|
information.
|
|
|
|
However, there were many other situations
|
|
where this could not be done. Therefore, there is a limit of one
|
|
process at a time inside either GS/OS or the ToolBox. GNO/ME
|
|
automatically enforces this restriction whenever a tool or GS/OS
|
|
call is made.
|
|
|
|
The method and details of making GS/OS
|
|
calls does not change! The calls listed below have been expanded
|
|
transparently. There are no new parameters and no new parameter
|
|
values. In all cases, the corresponding ProDOS-16 interface calls
|
|
are also supported, except ExpandPath and other calls which do
|
|
not exist in ProDOS-16.
|
|
|
|
\section{Pathnames and Prefixes}
|
|
|
|
Normally under GS/OS there are 32 prefixes,
|
|
and these are all under control of the current application.
|
|
GNO/ME extends this concept to provide each process with it's own
|
|
copies of all prefixes. When a process modifies one of these
|
|
prefixes via the GS/OS SetPrefix call, it modifies only it's own
|
|
copy of that prefix --- the same numbered prefixes of any other
|
|
processes are not modified.
|
|
|
|
Pathname processing has been expanded in
|
|
GNO/ME. There are now two new special pathname operators that are
|
|
accepted by any GS/OS call that takes a pathname parameter:
|
|
|
|
\begin{verbatim}
|
|
. current working directory
|
|
.. parent directory
|
|
\end{verbatim}
|
|
|
|
For example, presume that the current
|
|
working directory (prefix 0) is \tt /foo/bar/moe\rm.
|
|
``\tt./ls\rm'' refers to the file ``\tt/foo/bar/moe/ls\rm'',
|
|
and since a pathname was specified, this overrides the shell's hash table.
|
|
``\tt../ls\rm`` refers to ``\tt/foo/bar/ls\rm''.
|
|
The operators can be combined, also, as in
|
|
``\tt../../ls\rm'' (``\tt/foo/ls\rm''), and
|
|
``\tt./.././ls\rm'' (``\tt/foo/bar/ls\rm'').
|
|
As you can see, the '.' operator is simply
|
|
removed and has no effect other than to force a full expansion of
|
|
the pathname.
|
|
|
|
Shorthand
|
|
\index{device!names}
|
|
device names (.d2, .d5, etc) as are used in the ORCA/Shell
|
|
are available only under System Software 6.0 and later.
|
|
The common pathname operator '\~' (meaning the home
|
|
directory) is handled by the shell; if the character appears in a
|
|
GS/OS call it is not treated specially.
|
|
|
|
\index{ChangePath}
|
|
\index{ClearBackupBit}
|
|
\index{Create}
|
|
\index{Destroy}
|
|
\index{ExpandPath}
|
|
\index{GetFileInfo}
|
|
\index{GetPrefix}
|
|
\index{Open}
|
|
\index{SetFileInfo}
|
|
\index{SetPrefix}
|
|
|
|
\begin{tabular}{ll}
|
|
\$2004 & ChangePath \\
|
|
\$200B & ClearBackupBit \\
|
|
\$2001 & Create \\
|
|
\$2002 & Destroy \\
|
|
\$200E & ExpandPath \\
|
|
\$2006 & GetFileInfo \\
|
|
\$200A & GetPrefix \\
|
|
\$2010 & Open \\
|
|
\$2005 & SetFileInfo \\
|
|
\$2009 & SetPrefix \\
|
|
\end{tabular}
|
|
|
|
|
|
\section{Named Prefixes}
|
|
|
|
In order to allow easy installation and
|
|
configuration of third-party software into all systems, GNO/ME
|
|
provides a feature called named prefixes. These prefixes are
|
|
defined in the
|
|
\index{/etc/namespace}
|
|
/etc/namespace file. Basically, since all UNIX
|
|
systems have /bin, /usr, /etc, and other similar standard
|
|
partitions, but Apple IIgs systems generally do not have these
|
|
partitions, named prefixes provide a way to simulate the UNIX
|
|
directories without forcing GNO/ME users to rename their
|
|
partitions (an arduous and problem-filled task).
|
|
|
|
Named prefixes are handled by the GNO
|
|
kernel in the same GS/OS calls described in Chapter 3 \bf Pathnames
|
|
and Prefixes\rm.
|
|
The format of the /etc/namespace file can be found in the
|
|
\bf namespace\rm(5) manual page.
|
|
|
|
Note that if you have a physical partition that matches the name of a
|
|
logical partition defined in the /etc/namespace file, then the physical
|
|
parition will not be visible while running GNO.
|
|
|
|
\section{Open File Tracking}
|
|
|
|
Previously, a major problem with the way
|
|
GS/OS handled open files was that unrelated programs could affect
|
|
each other's open files. For example, a Desk Accessory (or a
|
|
background program of any sort) could open a file and have it
|
|
closed without it's knowledge by the main application program.
|
|
This presented all kinds of problems for desk accessory authors.
|
|
Apple presented a partial solution with System Software 5.0.4,
|
|
but it wasn't enough for a true multitasking environment. GNO/ME
|
|
keeps track of exactly which process opened which file. It also
|
|
discontinues the concept of a global File Level, opting instead
|
|
for a per-process File Level. Any operations a process performs
|
|
on a file (opening, closing, etc.) do not affect any other
|
|
process' files.
|
|
|
|
In addition to this behavior, when a
|
|
process terminates in any manner all files that it currently has
|
|
opened will be closed automatically. This prevents problems of
|
|
the sort where a program under development terminates abnormally,
|
|
often leaving files open and formerly necessitating a reboot.
|
|
|
|
The Flush GS/OS call is not modified in
|
|
this manner as its effects are basically harmless.
|
|
|
|
\index{Close}
|
|
The Close call accepts a refNum parameter
|
|
of 0 (zero), to close all open files. This works the same way
|
|
under GNO/ME, except of course that only the files of the process
|
|
calling Close are in fact closed.
|
|
|
|
\begin{tabular}{ll}
|
|
\$2010 & Open \\
|
|
\$2014 & Close \\
|
|
\$201B & GetLevel \\
|
|
\$201A & SetLevel \\
|
|
\end{tabular}
|
|
|
|
\section{Quitting Applications}
|
|
|
|
The QUIT and QuitGS calls have been
|
|
modified to support the GNO/ME process scheme. Quitting to
|
|
another application, whether by specifying a pathname or by
|
|
popping the return stack, is accomplished with \bf execve\rm(2).
|
|
When there are no entries on the return stack, the process is
|
|
simply killed. See the \it GS/OS Reference Manual \rm for more
|
|
details on how the Quit stack works.
|
|
|
|
\section{Refnums and File Descriptors}
|
|
|
|
GS/OS tells you about open files in the
|
|
form of refNums (reference numbers). UNIX's term for the same
|
|
concept is ``file descriptor''. From a user's or programmer's view
|
|
of GNO/ME, these terms are identical and will be used as such;
|
|
which one depends on what seems most appropriate in context.
|
|
|
|
For each process, GNO/ME keeps track of
|
|
which files that particular process has opened. No other process
|
|
can directly access a file that another process opened (unless
|
|
programmed explicitly), because it doesn't have access to any
|
|
file descriptors other than its own. This is different from GS/OS
|
|
in that GS/OS allows access to a file even if a program guessed
|
|
the refNum, either deliberately or accidentally. This is one of
|
|
the aspects of process protection in GNO/ME.
|
|
|
|
All of the various I/O mechanisms that
|
|
GNO/ME supports (files, pipes, and TTYs) are handled with the
|
|
same GS/OS calls you are familiar with. When you create a pipe,
|
|
for example, you are returned file descriptors which, because of
|
|
synonymity with refNums, you can use in GS/OS calls. Not all
|
|
GS/OS calls that deal with files are applicable to a particular
|
|
file descriptor; these are detailed in the sections on pipes and
|
|
TTYs.
|
|
|
|
GNO/ME sets no limit on the number of files
|
|
a process may have open at one time. (Most UNIX's have a set
|
|
limit at 32).
|
|
|
|
\section{GNO/ME Character Devices}
|
|
|
|
\index{device!character|(}
|
|
GNO/ME supports a new range of character
|
|
device drivers. These drivers are not installed like normal GS/OS
|
|
drivers, but they are accessed the same way. There are the
|
|
following built-in drivers:
|
|
|
|
\begin{rawhtml}
|
|
<!-- cleantable-start -->
|
|
\end{rawhtml}
|
|
\begin{tabular}{ll}
|
|
\bf .TTYCO \rm &
|
|
\begin{minipage}[t]{8cm}
|
|
% latex2html gets confused here
|
|
\begin{rawhtml}
|
|
</b>
|
|
\end{rawhtml}
|
|
This is the GNO/ME console driver. The driver supports
|
|
the TextTools Pascal control codes, plus a few GNO/ME
|
|
specific ones. These are documented in Chapter 4
|
|
\bf TextTools Replacement\rm. This driver is highly
|
|
optimized both through the GS/OS and TextTools interfaces.
|
|
\end{minipage} \hfill \\
|
|
|
|
\index{.pty}
|
|
\index{.tty}
|
|
\bf .TTYA[0-9,A-F] \rm \\
|
|
\bf .PTYQ[0-9,A-F] \rm &
|
|
\begin{minipage}[t]{8cm}
|
|
Pseudo-terminal devices; PTYs are used for interprocess
|
|
communication and in network activities.
|
|
\end{minipage} \hfill \\
|
|
|
|
\index{.NULL}
|
|
\bf .NULL \rm &
|
|
\begin{minipage}[t]{8cm}
|
|
This driver is a bit bucket. Any data written to it is
|
|
ignored, and any attempt to read from it results in an
|
|
end-of-file error (\$4C).
|
|
\end{minipage} \hfill \\
|
|
\end{tabular}
|
|
\begin{rawhtml}
|
|
<!-- cleantable-end -->
|
|
\end{rawhtml}
|
|
|
|
Just as with GS/OS devices, these GNO/ME
|
|
drivers are accessed with the same
|
|
\index{Open}
|
|
\index{Read}
|
|
\index{Write}
|
|
\index{Close}
|
|
Open, Read, Write, and Close
|
|
calls that are used on files. Unlike GS/OS character devices, the
|
|
characteristics of GNO/ME drivers are controlled through the
|
|
\bf ioctl\rm(2) system call. The GS/OS Device calls (like DInfo, DStatus)
|
|
are not applicable to GNO/ME drivers. See the \bf ioctl\rm(2) and
|
|
\bf tty\rm(4) man pages for details.
|
|
|
|
Some GS/OS calls will return an error when
|
|
given a refNum referring to a GNO/ME character driver or pipe
|
|
because the concepts simply do not apply. The error returned will
|
|
be \$58 (Not a Block Device), and the calls are as follows:
|
|
|
|
\begin{tabular}{ll}
|
|
\$2016 & SetMark \\
|
|
\$2017 & GetMark \\
|
|
\$2018 & SetEOF \\
|
|
\$2019 & GetEOF \\
|
|
\$2015 & Flush \\
|
|
\$201C & GetDirEntry \\
|
|
\end{tabular}
|
|
|
|
GNO/ME loaded drivers (generally for serial
|
|
communications, but other uses are possible) are configured in the
|
|
\index{/etc/tty.config} \bf /etc/tty.config \rm file.
|
|
Each line in \index{/etc/tty.config}
|
|
\bf /etc/tty.config \rm describes one driver. The format of each line is:
|
|
|
|
\begin{verbatim}
|
|
filename slot devname
|
|
\end{verbatim}
|
|
|
|
\bf devname \rm is the name of the device as
|
|
it will be accessed (for example,
|
|
\index{.ttya}
|
|
\bf.ttya\rm). \bf slot \rm is the slot in the
|
|
device table from where the device will be accessed; it may refer
|
|
to one of the physical expansion slots, as TextTools will use the
|
|
specified driver when redirecting output to a slot. The \bf modem \rm
|
|
and \bf printer \rm port drivers are configured for slots 2 and 1,
|
|
respectively.
|
|
|
|
Pseudo-terminals are pre-configured into
|
|
the kernel. PTYs are discussed further in Chapter 6 \it Psuedo-Terminals
|
|
PTYs\rm.
|
|
|
|
Since .ttyco and the pseudo-terminals are
|
|
preconfigured in the GNO kernel, entries for these devices do
|
|
not appear in \index{/etc/tty.config} \bf /etc/tty.config\rm.
|
|
\index{device!character|)}
|
|
|
|
\section{Restartability}
|
|
|
|
GS/OS supports the concept of program
|
|
``restartability''. This allows programs which are written in a
|
|
certain way to remain in memory in a purgeable state so that if
|
|
they are invoked again, and their memory has not been purged,
|
|
they can be restarted without any disk access. This greatly
|
|
increases the speed with which restartable programs can be
|
|
executed.
|
|
|
|
The ORCA environment specifies whether or
|
|
not a program is restartable via a flag character in the SYSCMND
|
|
file. The GS/OS standard method, however, is to set the
|
|
appropriate flags bit in the GS/OS Quit call. This is the method
|
|
that GNO/ME supports. Provided with the GNO/ME standard library
|
|
is a routine \bf rexit\rm(3). \bf rexit\rm (3) only works with
|
|
ORCA/C 2.0. \bf rexit\rm(3) works just like the normal C \bf exit\rm(3)
|
|
call but it sets the restart flag when calling QuitGS.
|
|
|
|
The standard ORCA/C 1.3 libraries are not
|
|
restartable, but the ORCA/C 2.0 libraries are.
|
|
|
|
\section{Miscellaneous}
|
|
|
|
The following miscellaneous GS/OS calls have also been modified for GNO/ME:
|
|
|
|
\begin{rawhtml}
|
|
<!-- cleantable-start -->
|
|
\end{rawhtml}
|
|
\begin{tabular}{ll}
|
|
\$2027 GetName &
|
|
\begin{minipage}[t]{8cm}
|
|
\begin{rawhtml}
|
|
</b>
|
|
\end{rawhtml}
|
|
Returns the name on disk of the process. This only
|
|
returns valid information after an \bf execve\rm(2).
|
|
\end{minipage} \hfill \\
|
|
|
|
\$2003 OSShutdown &
|
|
\begin{minipage}[t]{8cm}
|
|
This call has been modified to kill all processes before
|
|
performing the actual shutdown operation.
|
|
\end{minipage} \hfill \\
|
|
\end{tabular}
|
|
\begin{rawhtml}
|
|
<!-- cleantable-end -->
|
|
\end{rawhtml}
|
|
|
|
|
|
%
|
|
% CHAPTER: Modifications to the Toolbox
|
|
%
|
|
|
|
\begin{latexonly}
|
|
\chapter{Modifications to the ToolBox}
|
|
\end{latexonly}
|
|
\begin{htmlonly}
|
|
\chapter{Chapter 4: Modifications to the ToolBox}
|
|
\end{htmlonly}
|
|
|
|
Several changes have been made to the
|
|
ToolBox, the most major of which is the replacement of the entire
|
|
TextTools tool set. The TextTools were replaced for a number of
|
|
reasons --- better control over text I/O, increased speed, and
|
|
emulation of ORCA's redirection system with as little overhead as
|
|
possible. Other changes were made to modify the behavior of some
|
|
tool calls to be more consistent with the idea of a multitasking
|
|
environment.
|
|
|
|
\section{TextTools Replacement}
|
|
|
|
The changes to the TextTools have turned it
|
|
into a much more powerful general I/O manager. The TextTools now
|
|
intrinsically handle pipes and redirection, and you can install
|
|
custom drivers for TextTools to use. Also, the TextTools have had
|
|
their old slot-dependence removed; the parameter that used to
|
|
refer to 'slot' in the original texttools calls now refers to a
|
|
driver number. A summary of driver numbers (including those that
|
|
come pre-installed into GNO) are as follows:
|
|
|
|
\index{device!driver}
|
|
\begin{tabular}{ll}
|
|
\bf{0} & null device driver \\
|
|
\bf{1} & serial driver (for printer port compatibility) \\
|
|
\bf{2} & serial driver (for modem port compatibility) \\
|
|
\bf{3} & console driver (Pascal-compatible 80-column text screen) \\
|
|
\bf{4--5} & user installed \\
|
|
\end{tabular}
|
|
|
|
See Chapter 3 \bf GNO/ME Character Devices\rm,
|
|
for information on configuring these drivers.
|
|
|
|
There are also new device types in the
|
|
TextTools; the complete list of supported device types and what
|
|
their slotNum's (from SetInputDevice, SetOutputDevice, etc) mean
|
|
is as follows:
|
|
|
|
\index{device!types|(}
|
|
|
|
\begin{rawhtml}
|
|
<!-- cleantable-start -->
|
|
\end{rawhtml}
|
|
|
|
\begin{tabular}{rll}
|
|
\begin{minipage}[t]{1cm}
|
|
\sloppy
|
|
\bf Type \rm
|
|
\end{minipage} \hfill &
|
|
\begin{minipage}[t]{5cm}
|
|
\sloppy
|
|
\begin{center}
|
|
\bf Use \rm
|
|
\end{center}
|
|
\end{minipage} \hfill &
|
|
\begin{minipage}[t]{5cm}
|
|
\sloppy
|
|
\bf slotNum \rm
|
|
\end{minipage} \hfill \\ \cline{1-3}
|
|
|
|
|
|
\begin{minipage}[b]{1cm}
|
|
\sloppy
|
|
\bf 0 \rm
|
|
\end{minipage} \hfill &
|
|
\begin{minipage}[t]{5cm}
|
|
\sloppy
|
|
Used to be \index{BASIC} BASIC text drivers. These
|
|
are no longer supported under GNO/ME, and setting I/O to
|
|
a BASIC driver actually selects a Pascal driver.
|
|
\end{minipage} \hfill &
|
|
\begin{minipage}[t]{5cm}
|
|
\sloppy
|
|
Not applicable.
|
|
\end{minipage} \hfill \\
|
|
|
|
|
|
\begin{minipage}[b]{1cm}
|
|
\sloppy
|
|
\bf 1 \rm
|
|
\end{minipage} \hfill &
|
|
\begin{minipage}[t]{5cm}
|
|
\sloppy
|
|
Pascal text driver. This is one of the drivers specified in
|
|
\index{/etc/ttys} /etc/ttys or built-in to GNO/ME.
|
|
\end{minipage} \hfill &
|
|
\begin{minipage}[t]{5cm}
|
|
\sloppy
|
|
Driver number as listed above.
|
|
\end{minipage} \hfill \\
|
|
|
|
|
|
\begin{minipage}[b]{1cm}
|
|
\sloppy
|
|
\bf 2 \rm
|
|
\end{minipage} \hfill &
|
|
\begin{minipage}[t]{5cm}
|
|
\sloppy
|
|
RAM-based Driver (documented in \it ToolBox Reference Volume 2\rm)
|
|
\end{minipage} \hfill &
|
|
\begin{minipage}[t]{5cm}
|
|
\sloppy
|
|
Pointer to the RAM-based driver's jump table.
|
|
\end{minipage} \hfill \\
|
|
|
|
|
|
\begin{minipage}[b]{1cm}
|
|
\sloppy
|
|
\bf 3 \rm
|
|
\end{minipage} \hfill &
|
|
\begin{minipage}[t]{5cm}
|
|
File redirection
|
|
\end{minipage} \hfill &
|
|
\begin{minipage}[t]{5cm}
|
|
refNum (file descriptor) of the file to access through TextTools.
|
|
\end{minipage} \hfill \\
|
|
\end{tabular}
|
|
\begin{rawhtml}
|
|
<!-- cleantable-end -->
|
|
\end{rawhtml}
|
|
|
|
% This is an attempt to do without the kludge below. Just comment it
|
|
% out for now
|
|
\begin{comment}
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% This is a really annoying kludge-fuck.
|
|
%
|
|
% latex2html doesn't currently seem to handle \parbox correctly.
|
|
% On the other hand, using \begin{verbatim} mode makes this table
|
|
% look ugly in postscript. Piece of crap.
|
|
%
|
|
% So instead we resort to duplicating this information. Be careful
|
|
% to update both versions, please.
|
|
%
|
|
|
|
\begin{latexonly}
|
|
\begin{tabular}{rll}
|
|
\parbox[b]{1cm}{
|
|
\sloppy
|
|
\bf Device Type \rm
|
|
} &
|
|
\parbox[t]{5cm}{
|
|
\sloppy
|
|
\bf Use \rm
|
|
} &
|
|
\parbox[t]{5cm}{
|
|
\sloppy
|
|
\bf slotNum \rm
|
|
} \\ \cline{1-3}
|
|
|
|
\parbox[t]{1cm}{
|
|
\sloppy
|
|
\bf 0 \rm
|
|
} &
|
|
\parbox[t]{5cm}{
|
|
\sloppy
|
|
Used to be BASIC text drivers. These
|
|
are no longer supported under GNO/ME, and set-\\ting I/O to
|
|
a BASIC driver actually selects a Pascal driver.
|
|
} &
|
|
\parbox[t]{5cm}{
|
|
\sloppy
|
|
Not applicable.
|
|
} \\
|
|
|
|
\parbox[t]{1cm}{
|
|
\sloppy
|
|
\bf 1 \rm
|
|
} &
|
|
\parbox[t]{5cm}{
|
|
\sloppy
|
|
Pascal text driver. This is one of
|
|
the drivers specified in /etc/ttys or built-in to GNO/ME.
|
|
} &
|
|
\parbox[t]{5cm}{
|
|
\sloppy
|
|
Driver number as listed above.
|
|
} \\
|
|
|
|
|
|
\parbox[t]{1cm}{
|
|
\sloppy
|
|
\bf 2 \rm
|
|
} &
|
|
\parbox[t]{5cm}{
|
|
\sloppy
|
|
RAM-based Driver (documented in \it ToolBox Reference Volume 2\rm)
|
|
} &
|
|
\parbox[t]{5cm}{
|
|
\sloppy
|
|
Pointer to the RAM-\\based driver's jump table.
|
|
} \\
|
|
|
|
|
|
\parbox[t]{1cm}{
|
|
\sloppy
|
|
\bf 3 \rm
|
|
} &
|
|
\parbox[t]{5cm}{
|
|
\sloppy
|
|
File redirection
|
|
} &
|
|
\parbox[t]{5cm}{
|
|
\sloppy
|
|
refNum (file descriptor) of the file to access through TextTools.
|
|
} \\
|
|
\end{tabular}
|
|
\end{latexonly}
|
|
|
|
%
|
|
% This is the html version. The tables look strange because of the
|
|
% formatting commands. They actually line up if those commands are
|
|
% removed.
|
|
%
|
|
|
|
\begin{htmlonly}
|
|
\begin{rawhtml}
|
|
<pre>
|
|
<b>Device
|
|
Type Use slotNum
|
|
-------------------------------------------------------------------</b>
|
|
<b>0</b> Used to be BASIC text drivers. These Not Applicable
|
|
are no longer supported under GNO/ME,
|
|
and setting I/O to a BASIC driver
|
|
actually selects a Pascal driver.
|
|
|
|
<b>1</b> Pascal text driver. This is one of Driver number as
|
|
the drivers specified in /etc/ttys listed above.
|
|
or built-in to GNO/ME.
|
|
|
|
<b>2</b> RAM-based Driver (documented in Pointer to the RAM-
|
|
<em>ToolBox Reference Volume 2</em>. based driver's jump
|
|
table.
|
|
|
|
<b>3</b> File redirection. refNum (file desc-
|
|
riptor) of the file
|
|
to access through
|
|
TextTools.
|
|
</pre>
|
|
\end{rawhtml}
|
|
\end{htmlonly}
|
|
%
|
|
% kludge-fuck ends
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
\end{comment}
|
|
|
|
\index{device!types|)}
|
|
\index{driver!console}
|
|
|
|
The new console driver supports all the
|
|
features of the old 80-column Pascal firmware, and adds a few
|
|
extensions, with one exception --- the codes that switched between
|
|
40 and 80 columns modes are not supported. It is not compatible
|
|
with the GS/OS
|
|
\index{.CONSOLE}
|
|
``.console'' driver. The control codes supported are as follows:
|
|
|
|
\index{\^{}C}
|
|
\index{\^{}Z}
|
|
\begin{tabular}{lll}
|
|
Hex & ASCII & Action \\ \cline{1-3}
|
|
01 & CTRL-A & Set cursor to flashing block \\
|
|
02 & CTRL-B & Set cursor to flashing underscore \\
|
|
03 & CTRL-C & Begin ``Set Text Window'' sequence \\
|
|
05 & CTRL-E & Cursor on \\
|
|
06 & CTRL-F & Cursor off \\
|
|
07 & CTRL-G & Perform FlexBeep \\
|
|
08 & CTRL-H & Move left one character \\
|
|
09 & CTRL-I & Tab \\
|
|
0A & CTRL-J & Move down a line \\
|
|
0B & CTRL-K & Clear to EOP (end of screen) \\
|
|
0C & CTRL-L & Clear screen, home cursor \\
|
|
0D & CTRL-M & Move cursor to left edge of line \\
|
|
0E & CTRL-N & Normal text \\
|
|
0F & CTRL-O & Inverse text \\
|
|
11 & CTRL-Q & Insert a blank line at the current cursor position \\
|
|
12 & CTRL-R & Delete the line at the current cursor position. \\
|
|
15 & CTRL-U & Move cursor right one character \\
|
|
16 & CTRL-V & Scroll display down one line \\
|
|
17 & CTRL-W & Scroll display up one line \\
|
|
18 & CTRL-X & Normal text, mousetext off \\
|
|
19 & CTRL-Y & Home cursor \\
|
|
1A & CTRL-Z & Clear entire line \\
|
|
1B & CTRL-[ & MouseText on \\
|
|
% This is a CTRL-\
|
|
1C & CTRL-\symbol{92} & Move cursor one character to the right \\
|
|
1D & CTRL-] & Clear to end of line \\
|
|
1E & CTRL-\^{} & Goto XY \\
|
|
1F & CTRL-\_{} & Move up one line \\
|
|
\end{tabular}
|
|
|
|
|
|
(\bf Note\rm: the \it Apple IIgs Firmware Reference \rm
|
|
incorrectly has codes 05 and 06 reversed. The codes listed here
|
|
are correct for both GNO/ME and the Apple IIgs 80-column
|
|
firmware.)
|
|
|
|
FlexBeep is a custom beep routine that
|
|
doesn't turn off interrupts for the duration of the noise as does
|
|
the default Apple IIgs beep. This means that the beep could sound
|
|
funny from time to time, but it allows other processes to keep
|
|
running. We also added two control codes to control what kind of
|
|
cursor is used. There are two types available as in most
|
|
text-based software; they are underscore for 'insert' mode, and
|
|
block for 'overstrike'. You may, of course, use whichever cursor
|
|
you like. For example, a communications program won't have need
|
|
of insert mode, so it can leave the choice up to the user.
|
|
|
|
|
|
|
|
The Set Text Window sequence (begun by a \$03 code) works as follows:
|
|
|
|
\begin{verbatim}
|
|
CTRL-C '[' LEFT RIGHT TOP BOTTOM
|
|
\end{verbatim}
|
|
|
|
CTRL-C is of course hex \$03, and '[' is the
|
|
open bracket character (\$5B). TOP, BOTTOM, LEFT, and RIGHT are
|
|
single-byte ASCII values that represent the margin settings.
|
|
Values for TOP and BOTTOM range from 0 to 23; LEFT and RIGHT
|
|
range from 0 to 79. TOP must be numerically less than BOTTOM;
|
|
LEFT must be less than RIGHT. Any impossible settings are
|
|
ignored, and defaults are used instead. The extra '[' in the
|
|
sequence helps prevent the screen from becoming confused in the
|
|
event that random data is printed to the screen.
|
|
|
|
After a successful Set Text Window
|
|
sequence, only the portion of the screen inside the 'window' will
|
|
be accessible, and only the window will scroll; any text outside
|
|
the window is not affected.
|
|
|
|
The cursor blinks at a rate defined by the
|
|
\index{control panel}
|
|
\bf Control Panel/Options/Cursor Flash \rm setting. Far left is no blinking
|
|
(solid), and far right is extremely fast blinking.
|
|
|
|
\tt ReadLine \rm (\$240C) now sports a complete line editor unlike the old
|
|
TextTools version. Following is a list of the editor commands.
|
|
|
|
\begin{tabular}{ll}
|
|
\index{\^{}D}
|
|
EOL & Terminates input (EOL is a parameter to the \_{}ReadLine call). \\
|
|
LEFT-ARROW & Move cursor to the left. \\
|
|
RIGHT-ARROW & Move cursor to right. It won't go past rightmost character. \\
|
|
DELETE & Delete the character to the left of the cursor. \\
|
|
CTRL-D & Delete character under the cursor. \\
|
|
OA-D & Delete character under the cursor. \\
|
|
OA-E & Toggles between overwrite and insert mode. \\
|
|
\end{tabular}
|
|
|
|
|
|
\tt ReadChar \rm (\$220C) has also been changed. The character returned may now
|
|
contain the key modification flags (\$C025) in the upper byte and
|
|
the character typed in the lower byte. This is still compatible
|
|
with the old TextTools ReadChar. To get the keyMod flags, call
|
|
\tt SetInGlobals \rm (\$090C) and
|
|
set the upper byte of the AND mask to \$FF. Typical parameters for
|
|
\tt SetInGlobals \rm to get this information are:
|
|
\index{ANDmask}
|
|
ANDmask\ =\ \$FF7F, ORmask\ =\ \$0000.
|
|
|
|
|
|
The default I/O masks have also been
|
|
changed. They are now
|
|
\index{ANDmask}
|
|
ANDmask\ =\ \$00FF, ORmask\ =\ \$0000. They are
|
|
set this way to extend the range of data that can be sent through
|
|
TextTools. GNO/ME Character drivers do not, like the previous
|
|
TextTools driver, require the hi-bit to be set.
|
|
|
|
The new TextTools are completely reentrant.
|
|
This means that any number of processes may be executing
|
|
TextTools calls at the same time, increasing system performance
|
|
somewhat. The TextTools are also the only toolset which is not
|
|
mutexed.
|
|
|
|
\index{driver!console}
|
|
The GNO/ME console driver also supports
|
|
flow-control in the form of Control-S and Control-Q. Control-S is
|
|
used to stop screen output, and Control-Q is used to resume
|
|
screen output.
|
|
|
|
\section{SysFailMgr}
|
|
|
|
|
|
The MiscTool call SysFailMgr (\$1503) has been
|
|
modified so that a process calling it is simply killed, instead
|
|
of causing system operation to stop. This was done because many
|
|
programs use SysFailMgr when a simple error message would have
|
|
sufficed. There are, however, some tool and GS/OS errors which
|
|
are truly system failure messages, and these do cause system
|
|
operation to stop. These errors are as follows:
|
|
|
|
\begin{tabular}{ll}
|
|
\$0305 & Damaged heartbeat queue detected. \\
|
|
\$0308 & Damaged heartbeat queue detected. \\
|
|
\$0681 & Event queue damaged. \\
|
|
\$0682 & Queue handle damaged. \\
|
|
\$08FF & Unclaimed sound interrupt. \\
|
|
\end{tabular}
|
|
|
|
What the system does after displaying the
|
|
message is the same as for a system panic.
|
|
|
|
|
|
\section{The Resource Manager}
|
|
|
|
The Resource Manager has been modified in
|
|
some subtle ways. First, GNO/ME makes sure that the
|
|
CurResourceApp value is always correct before a process makes a
|
|
Resource Manager call. Second, all open resource files are the
|
|
property of the Kernel. When a GetOpenFileRefnum call is made, a
|
|
new refnum is \bf dup\rm(2)'d to allow the process to access the
|
|
file. Having the Kernel control resource files also allows all
|
|
processes to share SYS.RESOURCES without requiring each process
|
|
to explicitly open it.
|
|
|
|
\section{The Event Manager}
|
|
|
|
|
|
GNO/ME starts up the Event Manager so it is
|
|
always available to the kernel and shell utilities. Changes were
|
|
made so that the Event Manager obtains keystrokes from the GNO/ME
|
|
\index{driver!console}
|
|
console driver (.ttyco). This allows UNIX-style utilities and
|
|
desktop applications to share the keyboard in a cooperative
|
|
manner. This also makes it possible to suspend desktop
|
|
applications; see Chapter 7, \bf Suspend NDA\rm.
|
|
|
|
EMStartUp sets the GNO console driver to
|
|
RAW mode via an \bf ioctl\rm(2) call, to allow the Event Manager
|
|
to get single keystrokes at a time, and to prevent users from
|
|
being able to kill the desktop application with \^C or other
|
|
interrupt characters. The four ``GetEvent'' routines,
|
|
GetNextEvent, GetOSEvent, EventAvail, and OSEventAvail now poll
|
|
the console for input characters instead of using an interrupt
|
|
handler.
|
|
|
|
\section{The Control Panel}
|
|
|
|
\index{CDA}
|
|
\index{control panel}
|
|
In most cases, the CDA menu is executed as
|
|
an interrupt handler. Since the Apple IIgs interrupt handler
|
|
firmware isn't reentrant, task switching is not allowed to occur
|
|
while the control panel is active. This basically means that all
|
|
processes grind to a halt. In many ways, however, this is not
|
|
undesirable. It definitely eases debugging, since a static system
|
|
is much easier to deal with than a dynamic system. Also, CDAs
|
|
assume they have full control of the text screen; multitasking
|
|
CDAs would confuse and be confused in terms of output.
|
|
|
|
During the execution of the Control Panel,
|
|
the original non-GNO/ME TextTools tool is reinstalled to prevent
|
|
compatibility problems. Another step, taken to maintain user
|
|
sanity, makes CDAs run under the kernel's process ID.
|
|
|
|
All the changes were made to two tool
|
|
calls: \tt SaveAll \rm (\$0B05) and \tt RestAll \rm (\$0C05).
|
|
|
|
\section{QDStartup}
|
|
|
|
The \tt QDStartup \rm (\$0204)
|
|
call has been modified to signal an error and
|
|
terminate any process that tries to make the call when it's
|
|
\index{controlling terminal}
|
|
controlling terminal is not the Apple IIgs console. This prevents
|
|
a user on a remote terminal from bringing up a desktop
|
|
application on the console, an operation he could not escape from
|
|
and one that would greatly annoy the user at the console.
|
|
|
|
Another change ensures that an attempt to
|
|
execute two graphics-based applications concurrently will fail;
|
|
the second process that tries to call
|
|
\tt QDStartUp \rm is killed and a diagnostic message is displayed
|
|
on the screen.
|
|
|
|
%
|
|
% CHAPTER: Process Management
|
|
%
|
|
|
|
\begin{latexonly}
|
|
\chapter{Process Management}
|
|
\end{latexonly}
|
|
\begin{htmlonly}
|
|
\chapter{Chapter 5: Process Management}
|
|
\end{htmlonly}
|
|
|
|
Before discussing process management using
|
|
Kernel calls, it would be wise to define just exactly what we
|
|
refer to when we say \it process\rm. A process is generally
|
|
considered to be a program in execution. ``A program is a
|
|
passive entity, while a process is an active entity.''
|
|
(Operating Systems Concepts p.73, Silberschatz and Peterson,
|
|
Addison-Wesley, 1989). The concept of process includes the
|
|
information a computer needs to execute a program (such as the
|
|
program counter, register values, etc).
|
|
|
|
In order to execute multiple processes, the
|
|
operating system (GNO/ME and GS/OS in this case) has to make
|
|
decisions about which process to run and when. GNO/ME supports
|
|
what is termed \it preemptive multitasking\rm, which means that
|
|
processes are interrupted after a certain amount of time (their
|
|
time slice), at which point another process is allowed to run.
|
|
The changing of machine registers to make the processor execute a
|
|
different process is called a \index{context switch}
|
|
\it context switch\rm, and the
|
|
information the operating system needs to do this is called its
|
|
\it context\rm.
|
|
The GNO kernel maintains a list of all active processes, and
|
|
assigns time slices to each process according to their order in
|
|
the list. When the kernel has run through all the processes, it
|
|
starts again at the beginning of the list. This is called \it round-robin
|
|
scheduling\rm. Under certain circumstances, a process can
|
|
actually execute longer than its allotted time slice because task
|
|
switches are not allowed during a GS/OS or ToolBox call. In these
|
|
cases, as soon as the system call is finished the process is
|
|
interrupted.
|
|
|
|
Processes can give up the rest of their
|
|
time slice voluntarily (but not necessarily explicitly) in a
|
|
number of ways, terminal input being the most common. In this
|
|
case, the rest of the time slice is allocated to the next process
|
|
in line (to help smooth out scheduling). A process waiting on
|
|
some event to happen is termed \index{blocked processes} \it blocked\rm.
|
|
There are many ways this can happen, and each will be mentioned in its place.
|
|
|
|
An important item to remember is the \it process
|
|
ID\rm. This is a number which uniquely identifies a process. The
|
|
ID is assigned when the process is created, and is made available
|
|
for reassignment when the process terminates. A great many system
|
|
calls require process IDs as input. Do not confuse this with a
|
|
userID, which is a system for keeping track of memory allocation
|
|
by various parts of the system, and is handled (pardon the pun)
|
|
by the Memory Manager tool set. Also, do not confuse Memory
|
|
Manager userID's with Unix user ID's --- numbers which are assigned
|
|
to the various human users of a multiuser machine.
|
|
|
|
There are two methods for creating new
|
|
processes: the system call \bf fork\rm(2)
|
|
(or \bf fork2\rm(2))
|
|
and the library routine \bf exec\rm(3)
|
|
(specifics for calling these functions and others is in Appendix
|
|
A \it Making System Calls\rm). \bf fork \rm starts up a process
|
|
which begins execution at an address you specify. \bf exec \rm
|
|
starts up a process by loading an executable file (S16 or EXE). \bf fork \rm
|
|
is used mainly for use inside a specific application, such as
|
|
running shell built-ins in the \index{background} background, or setting up
|
|
independent entities inside a program. Forked processes have some
|
|
limitations, due to the hardware design of the Apple IIgs. The
|
|
parent process (the process which called fork) must still exist
|
|
when the
|
|
\index{process!child|(}
|
|
children die, either via \bf kill \rm or by simply
|
|
exiting. This is because the forked children share the same
|
|
memory space as the parent; the memory the children execute from
|
|
is tagged with the parent's userID. If the parent terminated
|
|
before the children, the children's code would be deallocated and
|
|
likely overwritten. A second caveat with \bf fork \rm is the
|
|
difference between it's UNIX counterpart. UNIX \bf fork \rm
|
|
begins executing the child at a point directly after the call to \bf fork\rm.
|
|
This cannot be accomplished on the Apple IIgs because virtual
|
|
memory is required for such an operation; thus the need to
|
|
specify a \bf fork \rm child as a C function. Note that an
|
|
appropriately written
|
|
\index{assembly language programs}
|
|
assembly language program need not
|
|
necessarily have these restrictions. When a process is forked,
|
|
the child process is given it's own direct page and stack space
|
|
under a newly allocated userID, so that when the child terminates
|
|
this memory is automatically freed.
|
|
|
|
\bf exec\rm(3) is used when the process you
|
|
wish to start is a GS/OS load file (file type S16 and EXE). \bf exec \rm
|
|
follows the procedure outlined in the \it GS/OS Reference Manual \rm
|
|
for executing a program, and sets up the new program's
|
|
environment as it expects. After \bf exec \rm has loaded the
|
|
program and set up it's environment, the new process is started
|
|
and \bf exec \rm returns immediately.
|
|
|
|
Both \bf fork\rm(2) and \bf exec\rm(3) return
|
|
the process ID of the child. The parent may use this process ID
|
|
to send \it signals \rm to the child, or simply wait for the child
|
|
to exit with the \bf wait\rm(2) system call; indeed, this is the
|
|
most common use. Whenever a child process terminates or is
|
|
stopped (See Chapter 6 \it Interprocess Communication\rm),
|
|
the kernel creates a
|
|
packet of information which is then made available to the
|
|
process' parent. If the parent is currently inside a wait call,
|
|
the call returns with the information. If the parent is off doing
|
|
something else, the kernel sends the parent process a
|
|
\tt SIGCHLD \rm signal. The default is to ignore \tt SIGCHLD\rm,
|
|
but a common technique is to install a handler for \tt SIGCHLD\rm,
|
|
and to make a \bf wait \rm call inside the handler to retrieve
|
|
the relevant information.
|
|
|
|
\bf exec\rm(3) is actually implemented as
|
|
two other system calls: \bf fork\rm(2), and one called \bf execve\rm(2).
|
|
\bf execve \rm loads a program from an executable file, and
|
|
begins executing it. The current process' memory is deallocated.
|
|
The shell uses a \bf fork\rm/\bf execve \rm pair explicitly,
|
|
so it can set up redirection and handle job control.
|
|
|
|
\index{process!child|)}
|
|
|
|
\section{Process Table}
|
|
|
|
Information about processes is maintained
|
|
in the process table, which contains one entry for each possible
|
|
process (\bf NPROC\rm, defined in the C header file \tt <gno/conf.h>\rm.
|
|
There is other per-process information spread about the kernel, but
|
|
those are usually used for maintaining compatibility with older
|
|
software, and thus are not described here. Please note that the
|
|
data in this section is informational only (e.g. for programs
|
|
like \bf ps\rm(1)). Do not attempt to modify kernel data
|
|
structures or the GNO Kernel will likely respond with a
|
|
resounding crash. Only 'interesting' fields are documented.
|
|
|
|
Copies of process entries should be
|
|
obtained by using the Kernel Virtual Memory (KVM) routines
|
|
(\bf kvm\_{}open\rm(2), and so forth).
|
|
These are documented in the electronic manual pages.
|
|
|
|
\begin{description}
|
|
|
|
\item[processState]
|
|
Processes have a
|
|
state associate with them. The state of the process is a
|
|
description of what the process is doing. The possible process
|
|
states (as listed in
|
|
\tt <gno/proc.h> \rm
|
|
and described here) are:
|
|
|
|
\begin{rawhtml}
|
|
<!-- cleantable-start -->
|
|
\end{rawhtml}
|
|
|
|
\begin{tabular}{ll}
|
|
|
|
RUNNING &
|
|
\begin{minipage}[t]{8cm}
|
|
The process is currently in execution.
|
|
\end{minipage} \hfill \\
|
|
|
|
READY &
|
|
\begin{minipage}[t]{8cm}
|
|
The process is not currently executing, but is ready to be
|
|
executed as soon as it is assigned a time slice.
|
|
\end{minipage} \hfill \\
|
|
|
|
BLOCKED &
|
|
\begin{minipage}[t]{8cm}
|
|
\index{blocked processes}
|
|
The process is waiting for a slow I/O operation to
|
|
complete (for instance, a read from a TTY).
|
|
\end{minipage} \hfill \\
|
|
|
|
NEW &
|
|
\begin{minipage}[t]{8cm}
|
|
The process has been created, but has not executed yet.
|
|
\end{minipage} \hfill \\
|
|
|
|
SUSPENDED &
|
|
\begin{minipage}[t]{8cm}
|
|
The process was stopped with SIGSTOP, SIGTSTP,
|
|
SIGTTIN, or SIGTTOU.
|
|
\end{minipage} \hfill \\
|
|
|
|
WAITING &
|
|
\begin{minipage}[t]{8cm}
|
|
The process is waiting on a semaphore ``signal'' operation.
|
|
Programs waiting for data from a pipe have this state.
|
|
\end{minipage} \hfill \\
|
|
|
|
WAITSIGCH &
|
|
\begin{minipage}[t]{8cm}
|
|
The process is waiting to receive a SIGCHLD signal.
|
|
\end{minipage} \hfill \\
|
|
|
|
PAUSED &
|
|
\begin{minipage}[t]{8cm}
|
|
The process is waiting for any signal.
|
|
\end{minipage} \hfill \\
|
|
|
|
\end{tabular}
|
|
|
|
\begin{rawhtml}
|
|
<!-- cleantable-end -->
|
|
\end{rawhtml}
|
|
|
|
|
|
\item[ttyID]
|
|
\index{device!number}
|
|
\index{device!names}
|
|
The device number of the
|
|
\index{controlling terminal}
|
|
controlling TTY for this process.
|
|
This is not a GS/OS refnum; rather, it is an index into the kernel's internal
|
|
character device table.
|
|
The value of this field can be interpreted as follows:
|
|
|
|
\index{.pty}
|
|
\index{.tty}
|
|
\index{.ttya}
|
|
\index{.ttyb}
|
|
\begin{tabular}{rl}
|
|
\bf{0} & .null \\
|
|
\bf{1} & .ttya \\
|
|
\bf{2} & .ttyb \\
|
|
\bf{3} & .ttyco \\
|
|
\bf{6} & .ptyq0 pty0 master side \\
|
|
\bf{7} & .ttyq0 pty0 slave side \\
|
|
\end{tabular}
|
|
|
|
Other values may be appropriate depending
|
|
on the
|
|
\index{/etc/tty.config}
|
|
\tt /etc/tty.config \rm file. Namely, \bf 1 \rm and \bf 2 \rm
|
|
(by default the modem and printer port drivers), and \bf 4 \rm and
|
|
\bf 5 \rm (unassigned by default) may be assigned to different devices.
|
|
|
|
|
|
\item[ticks]
|
|
The number of full ticks this process has executed. If a process gives up
|
|
it's time slice due to an I/O operation, this value is not incremented.
|
|
A tick is 1/60 second.
|
|
|
|
\item[alarmCount]
|
|
\index{alarmCount}
|
|
If an
|
|
\index{alarm}
|
|
\bf alarm\rm(2) request was made, this is the number of seconds
|
|
remaining until the process is sent SIGALRM.
|
|
|
|
\item[openFiles]
|
|
This is a structure which stores information about the files a
|
|
process has open. See \tt struct ftable \rm and \tt struct fdentry \rm
|
|
in \tt <gno/proc.h> \rm.
|
|
|
|
\item[irq\_{}A, irq\_{}X, irq\_{}Y, irq\_{}S, irq\_{}D, irq\_{}B,
|
|
irq\_{}P, irq\_{}state, irq\_{}PC, irq\_{}K]
|
|
\index{context switch}
|
|
Context information for the process. These fields are the values of the
|
|
\index{65816 registers}
|
|
65816 registers
|
|
at the last context switch. They only truly represent the
|
|
machine state of the process if the process is not RUNNING.
|
|
|
|
\item[args]
|
|
\index{args}
|
|
This is a NULL-terminated (C-style) string that contains the command line
|
|
with which the process was invoked. This string begins with
|
|
\index{BYTEWRKS}
|
|
``BYTEWRKS'', the shell identifier.
|
|
|
|
\end{description}
|
|
|
|
For more details and an example of how to
|
|
investigate process information, look at the source code for the
|
|
\index{CDA}
|
|
``GNO Snooper CDA''.
|
|
|
|
\section{Task Switching}
|
|
|
|
\index{context switch|(}
|
|
|
|
As mentioned earlier, user code can often
|
|
unwittingly initiate a context switch by reading from the console
|
|
(and other miscellaneous things). There are a few situations
|
|
where this can cause a problem, namely inside interrupt handlers.
|
|
While the kernel makes an attempt to prevent this, it cannot
|
|
predict every conceivable problem. The kernel attempts to detect
|
|
and prevent context switches inside interrupt handlers by
|
|
checking for the following situations.
|
|
|
|
\begin{itemize}
|
|
\item Is the system busy flag non-zero? (The busy flag is located at
|
|
address \tt \$E100FF\rm.)
|
|
|
|
\item Is the ``No-Compact'' flag set? (Located at \tt\$E100CB\rm.)
|
|
|
|
\item Does the stack pointer point to anything in thr range
|
|
\tt \$0100-\$01FF\rm?
|
|
|
|
\item Is the interrupt bit in the processor status register set?
|
|
\end{itemize}
|
|
|
|
If any of these conditions are met, a
|
|
context switch will not take place. This can cause problems in
|
|
certain circumstances. The basic rule is to avoid making Kernel
|
|
calls that might cause a context switch or change in process
|
|
state from inside an interrupt handler. This includes the
|
|
following:
|
|
|
|
\begin{itemize}
|
|
\item reading from the console
|
|
\item accessing a pipe
|
|
\item any of the following kernel traps:
|
|
\bf \_{}execve\rm(2) (or other calls in the \bf exec \rm family),
|
|
\bf fork\rm(2),
|
|
\bf fork2\rm(2),
|
|
\bf kill\rm(2),
|
|
\bf pause\rm(2),
|
|
\bf procreceive\rm(2),
|
|
\bf sigpause\rm(2),
|
|
or
|
|
\bf wait\rm(2).
|
|
\end{itemize}
|
|
|
|
Calls such as \bf procsend\rm(2), however, may be used from inside
|
|
an interrupt handler, and in fact are very useful in such situations.
|
|
|
|
\index{context switch|)}
|
|
|
|
\section{Job Control}
|
|
|
|
Job control is a feature of the kernel that
|
|
helps processes orderly share a terminal. It prevents such
|
|
quandaries as ``What happens when two processes try to read
|
|
from the terminal at the same time?''.
|
|
|
|
Job control works by assigning related
|
|
processes to a \it process group\rm. For example, all of the
|
|
processes in a pipeline belong to one process group. Terminal
|
|
\index{device!driver}
|
|
device drivers also belong to process groups, and when the
|
|
process group of a job does not match that of its
|
|
\index{controlling terminal}
|
|
\it controlling terminal \rm
|
|
the job is said to be in the \index{background} background.
|
|
Background jobs have access to their controlling terminal restricted in
|
|
certain ways.
|
|
|
|
\begin{itemize}
|
|
\item If a background job attempts to read from the terminal, the
|
|
kernel suspends the process by sending the \tt SIGTTIN \rm signal.
|
|
|
|
\item The interrupt signals \tt SIGTSTP \rm and \tt SIGINT\rm,
|
|
generated by \^Z and \^C respectively, are sent only to the
|
|
foregound job. This allows backgrounded jobs to proceed without
|
|
interruption.
|
|
|
|
\item Certain \bf ioctl\rm(2) calls cannot be made by a background job;
|
|
the result is a \tt SIGTTIN \rm signal.
|
|
\end{itemize}
|
|
|
|
Job control is accessed by software through the \bf tcnewpgrp\rm,
|
|
\bf tctpgrp, and \bf settpgrp\rm(2) system calls.
|
|
See the \bf jobcontrol\rm(2) and \bf ioctl\rm(2) man pages.
|
|
|
|
%
|
|
% CHAPTER: Interprocess Communication
|
|
%
|
|
|
|
\begin{latexonly}
|
|
\chapter{Interprocess Communication}
|
|
\end{latexonly}
|
|
\begin{htmlonly}
|
|
\chapter{Chapter 6: Interprocess Communication}
|
|
\end{htmlonly}
|
|
|
|
\tiny
|
|
|
|
\begin{verse}
|
|
Oh, give me a home \\
|
|
Where the semaphores roam, \\
|
|
and the pipes are not deadlocked all day ... \\
|
|
|
|
--- unknown western hero
|
|
\end{verse}
|
|
|
|
\normalsize
|
|
|
|
The term Interprocess Communication (\it IPC\rm)
|
|
covers a large range of operating system features. Any time a
|
|
process needs to send information to another process some form of
|
|
IPC is used. The GNO Kernel provides several basic types:
|
|
semaphores, signals, pipes, messages, ports, and
|
|
pseudo-terminals. These IPC mechanisms cover almost every
|
|
conceivable communication task a program could possibly need to
|
|
do.
|
|
|
|
\section{Semaphores}
|
|
|
|
In the days before radio, when two ships
|
|
wished to communicate with each other to decide who was going
|
|
first to traverse a channel wide enough only for one, they used
|
|
multicolored flags called semaphores. Computer scientists, being
|
|
great lovers of anachronistic terms, adopted the term and meaning
|
|
of the word semaphore to create a way for processes to
|
|
communicate when accessing shared information.
|
|
|
|
GNO/ME, like other multitasking systems,
|
|
provides applications with semaphore routines. Semaphores
|
|
sequentialize access to data by concurrently executing processes.
|
|
You should use semaphores whenever two or more processes want to
|
|
access shared information. For example, suppose there were three
|
|
processes, each of which accepted input from user terminals and
|
|
stored this input into a buffer in memory. Suppose also that
|
|
there is another process which reads the information out of the
|
|
buffer and stores it on disk. If one of the processes putting
|
|
information in the buffer (writer process) was in the middle of
|
|
storing information in the buffer when a
|
|
\index{context switch}
|
|
context switch occurred,
|
|
and one of the other processes then accessed the buffer, things
|
|
would get really confused. Code that accesses the buffer should
|
|
not be interrupted by another process that manipulates the
|
|
buffer; this code is called a
|
|
\index{critical section}
|
|
\it critical section\rm; in order to operate properly, this code
|
|
must not be interrupted by any other attempts to access the buffer.
|
|
|
|
To prevent the buffer from becoming
|
|
corrupted, a semaphore would be employed. As part of it's
|
|
startup, the application that started up the other processes
|
|
would also create a semaphore using the \bf screate\rm(2) system
|
|
call with a parameter of 1. This number means (among other
|
|
things) that only one process at a time can enter the critical
|
|
section, and is called the \it count\rm.
|
|
|
|
When a process wishes to access the buffer,
|
|
it makes a \bf swait\rm(2), giving as argument the semaphore
|
|
number returned by \bf screate\rm(2). When it's done with the
|
|
buffer, it makes an \bf ssignal\rm(2) call to indicate this fact.
|
|
|
|
This is what happens when \bf swait \rm is
|
|
called: the kernel first decrements the count. If the count is
|
|
then less than zero, the kernel suspends the process, because a
|
|
count of less than zero indicates that another process is already
|
|
inside a critical section. This suspended state is called
|
|
'waiting' (hence the name of \bf swait\rm). Every process that
|
|
tries to call \bf swait \rm with count < 0 will be suspended;
|
|
a queue of all the processes currently waiting on the semaphore
|
|
is associated with the semaphore.
|
|
|
|
Now, when the process inside the critical
|
|
section leaves and executes \bf ssignal\rm, the kernel
|
|
increments the count. If there are processes waiting for the
|
|
semaphore, the kernel chooses one arbitrarily and restarts it.
|
|
When the process resumes execution at its next time slice, its
|
|
\bf swait \rm
|
|
call will finish executing and it will have exclusive control of
|
|
the critical section. This cycle continues until there are no
|
|
processes waiting on the semaphore, at which point its count will
|
|
have returned to 1.
|
|
|
|
When the semaphore is no longer needed, you
|
|
should dispose of it with the \bf sdelete\rm(2) call. This call
|
|
frees any processes that might be waiting on the semaphore and
|
|
returns the semaphore to the semaphore pool.
|
|
|
|
One must be careful in use of semaphores or
|
|
\index{deadlock}
|
|
\it deadlock \rm can occur.
|
|
|
|
There are (believe it or not) many
|
|
situations in everyday programming when you may need semaphores,
|
|
moreso than real UNIX systems due to the Apple IIgs's lack of
|
|
virtual memory. The most common of these is your C or Pascal
|
|
compiler's stdio library; these are routines like \bf printf\rm(3)
|
|
and \bf writeln\rm(3). In many cases, these libraries use global
|
|
variables and buffers. If you write a program which forks a
|
|
\index{process!child}
|
|
child process that shares program code with the parent process (i.e.
|
|
doesn't \bf execve\rm(2) to another executable), and that child
|
|
and the parent both use \it non-reentrant \rm library calls, the
|
|
library will become confused. In the case of text output
|
|
routines, this usually results in garbaged output.
|
|
|
|
Other library routines can have more
|
|
disastrous results. For example, if a parent's
|
|
\bf free\rm(3) or \bf dispose\rm(3)
|
|
memory management call is interrupted, and the child makes a
|
|
similar call during this time, the linked lists that the library
|
|
maintains to keep track of allocated memory could become
|
|
corrupted, resulting most likely in a program crash.
|
|
|
|
GNO/ME provides \it mutual exclusion \rm
|
|
(i.e., lets a maximum of one process at a time execute the code)
|
|
automatically around all Toolbox and GS/OS calls as described in
|
|
Chapter 3, and also uses semaphores internally in many other
|
|
places. Any budding GNO/ME programmer is well advised to
|
|
experiment with semaphores to get a feel for when and where they
|
|
should be used. Examples of semaphore use can be found in the
|
|
sample source code, notably \tt dp.c \rm
|
|
(Dining Philosophers demo) and \tt pipe*.c \rm
|
|
(a sample implementation of pipes written entirely in C).
|
|
|
|
\section{Signals}
|
|
|
|
|
|
Another method of IPC is software signals.
|
|
Signals are similar to hardware interrupts in that they are
|
|
asynchronous; that is, a process receiving a signal does not have
|
|
to be in a special mode, does not have to wait for it. Also like
|
|
hardware interrupts, a process can install signal handlers to
|
|
take special action when a signal arrives. Unlike hardware
|
|
interrupts, signals are defined and handled entirely through
|
|
software.
|
|
|
|
Signals are generally used to tell a
|
|
process of some event that has occurred. Between the
|
|
system-defined and user-defined signals, there is a lot of things
|
|
you can do. GNO/ME currently defines 32 different signals. A list
|
|
of signals and their codes can be found in \bf signal\rm(2) and
|
|
the header file \tt <gno/signal.h>\rm.
|
|
|
|
There are three types of default actions
|
|
that occur upon receipt of a signal. The process receiving the
|
|
signal might be terminated, or stopped; or, the signal might be
|
|
ignored. The default action of any signal can be changed by a
|
|
process, with some exceptions. Not all of the defined signals are
|
|
currently used by GNO/ME, as some are not applicable to the Apple
|
|
IIgs, or represent UNIX features not yet implemented in GNO/ME .
|
|
Here is a list of the signals that are used by GNO/ME.
|
|
|
|
\begin{description}
|
|
\item[SIGINT]
|
|
This signal is sent to the
|
|
foreground job when a user types \^C at the terminal
|
|
keyboard.
|
|
\item[SIGKILL]
|
|
The default
|
|
action of this signal (termination) cannot be changed.
|
|
This provides a sure-fire means of stopping an otherwise
|
|
unstoppable process.
|
|
\item[SIGPIPE]
|
|
Whenever a process tries to
|
|
write on a pipe with no readers, it is sent this signal.
|
|
SIGALRM SIGALRM is sent when an
|
|
alarm timer expires (counts down to zero). An application
|
|
can start an alarm timer with the
|
|
\index{alarm}
|
|
\bf alarm\rm(2)
|
|
\begin{rawhtml}
|
|
</b>
|
|
\end{rawhtml}
|
|
\rm system call.
|
|
\item[SIGTERM]
|
|
This is the default signal
|
|
sent by \bf kill\rm(1). Use of this signal allows
|
|
applications to clean up (delete temporary files, free
|
|
system resources like semaphores, etc) before terminating
|
|
at the user's bequest.
|
|
\item[SIGSTOP]
|
|
This signal is used to stop
|
|
a process' execution temporarily. Like SIGKILL, processes
|
|
are not allowed to install a handler for this signal.
|
|
\item[SIGCONT]
|
|
To restart a stopped process, send this signal.
|
|
\item[SIGTSTP]
|
|
This is similar to SIGSTOP,
|
|
but is sent when the user types \^Z at the keyboard.
|
|
Unlike SIGSTOP, this signal can be ignored, caught, or
|
|
blocked.
|
|
\item[SIGCHLD]
|
|
\index{process!child}
|
|
A process receives this
|
|
signal whenever a child process is stopped or terminates.
|
|
\bf gsh \rm uses this to keep track of jobs, and the wait
|
|
system call waits for this signal to arrive before
|
|
exiting.
|
|
\item[SIGTTIN]
|
|
This signal also stops a process. It is sent to \index{background}
|
|
background jobs that try to get input from the terminal.
|
|
\item[SIGTTOU]
|
|
Similar to SIGTTIN, but is
|
|
sent when a background process tries to write to the
|
|
terminal. This behavior is optional and is by default
|
|
turned off.
|
|
\item[SIGUSR1, SIGUSR2]
|
|
These two signals are
|
|
reserved for application authors. Their meaning will
|
|
change from application to application.
|
|
\end{description}
|
|
|
|
As you can see, signals are used by many
|
|
aspects of the system. For detailed information on what various
|
|
signals mean, consult the appropriate electronic manual page ---
|
|
see \bf tty\rm(4), \bf wait\rm(2), and \bf signal\rm(2).
|
|
|
|
For an example of signal usage, consider a
|
|
print spooler. A print spooler takes files that are put in the
|
|
spool directory on a disk and sends the data in the files to a
|
|
printer. There are generally two parts to a print spooler: The
|
|
\index{daemon}
|
|
\it daemon\rm,
|
|
a process that resides in memory and performs the transfer of
|
|
data to the printer in the background; and the spooler. There can
|
|
be many different types of spoolers, say one for desktop
|
|
printing, one for printing source code, etc. To communicate to
|
|
the daemon that they have just placed a new file in the spool
|
|
directory, the spoolers could send the daemon SIGUSR. The daemon
|
|
will have a handler for SIGUSR, and that handler will locate the
|
|
file and set things up so the print will begin. Note that the
|
|
actual implementation of the print spooling system in GNO/ME,
|
|
\bf lpr\rm(1) and \bf lpd\rm(8),
|
|
is somewhat more complex and uses messages and
|
|
ports instead of signals. However, an earlier version of the
|
|
spooler software \it did \rm use signals for communication.
|
|
|
|
Signals should not be sent from inside an
|
|
interrupt handler, nor from inside a GS/OS or Toolbox call.
|
|
Window Manager update routines are a prime example of code that
|
|
should not send signals; they are executed as part of a tool
|
|
call. The GS/OS aspect of this limitation is a little harder to
|
|
come up against. GS/OS does maintain a software signal facility
|
|
of it's own, used to notify programs when certain low-level
|
|
events have occurred. Do not confuse these GS/OS signals with
|
|
GNO/ME signals, and above all, don't send a GNO/ME signal from a
|
|
GS/OS signal handler.
|
|
|
|
When a process receives a signal for which
|
|
it has installed a handler, what occurs is similar to a
|
|
\index{context switch}
|
|
context switch. The process' context is saved on the stack, and the
|
|
context is set so that the signal handler routine will be
|
|
executed. Since the old context is stored on the stack, the
|
|
signal handler may if it wishes return to some other part of the
|
|
program. It accomplishes this by setting the stack pointer to a
|
|
value saved earlier in the program and jumping to the appropriate
|
|
place. Jumps like this can be made with C's
|
|
\bf setjmp\rm(3) and \bf longjmp \rm(3)
|
|
functions. The following bit of code demonstrates this ability.
|
|
|
|
\begin{verbatim}
|
|
void sighandler (int sig, int code)
|
|
{
|
|
printf("Got a signal!");
|
|
longjmp(jmp_buf);
|
|
}
|
|
|
|
void routine(void)
|
|
{
|
|
signal(SIGUSR, sighandler);
|
|
if (setjmp(jmp_buf)) {
|
|
printf("Finally done! Sorry for all that...\n");
|
|
} else {
|
|
while(1) {
|
|
printf("While I wait I will annoy you!\n");
|
|
}
|
|
}
|
|
}
|
|
\end{verbatim}
|
|
|
|
% gdr: this is the spot where I left off reviewing the postscript output
|
|
|
|
This program basically prints an annoying
|
|
message over and over until SIGUSR is received. At that point,
|
|
the handler prints ``Got a Signal!'' and jumps back to
|
|
the part of the if statement that prints an apology. If the
|
|
signal handler hadn't made the \bf longjmp\rm, when the handler
|
|
exited control would have returned to the exact place in the \bf while \rm
|
|
loop that was interrupted.
|
|
|
|
\index{assembly language programs}
|
|
Similar techniques can be applied in assembly language.
|
|
|
|
\section{Pipes}
|
|
|
|
This third form of IPC implemented in
|
|
GNO/ME is one of the most powerful features ever put into an
|
|
operating system. A pipe is a conduit for information from one
|
|
process to another. Pipes are accessed just like regular files;
|
|
the same GS/OS and ToolBox calls currently used to manipulate
|
|
files are also used to manipulate pipes. When combined with
|
|
GNO/ME standard I/O features, pipes become very powerful indeed.
|
|
For examples on how to use \bf gsh \rm to connect applications
|
|
with pipes, see the \it GNO Shell Reference Manual\rm.
|
|
|
|
Pipes are unidirectional channels between
|
|
processes. Pipes are created with the \bf pipe\rm(2) system call,
|
|
which returns two GS/OS refNums; one for the write end, and one
|
|
for the read end. An attempt to read from the write end or
|
|
vice-versa results in an error.
|
|
|
|
Pipes under GNO/ME are implemented as a
|
|
circular buffer of 4096 bytes. Semaphores are employed to prevent
|
|
the buffer from overflowing, and to maintain synchronization
|
|
between the processes accessing the pipe. This is done by
|
|
creating two semaphores; their counts indicate how many bytes are
|
|
available to be read and how many bytes may be written to the
|
|
buffer (0 and 4096 initially). If an I/O operation on the pipe
|
|
would result in the buffer being emptied or filled, the calling
|
|
process is \index{blocked processes} blocked until the data (or space)
|
|
becomes available.
|
|
|
|
The usual method of setting up a pipeline
|
|
between processes, used by \bf gsh \rm and utilities such as
|
|
script, is to make the \bf pipe \rm call and then \bf fork\rm(2)
|
|
off the processes to be connected by the pipe.
|
|
|
|
\begin{verbatim}
|
|
|
|
/* No error checking is done in this fragment. This is
|
|
* left as an exercise for the reader.
|
|
*/
|
|
|
|
int fd[2];
|
|
int
|
|
testPipe(void)
|
|
{
|
|
pipe(fd); /* create the pipe */
|
|
fork(writer); /* create the writer process */
|
|
fork(reader); /* create the reader process */
|
|
close(fd[0]); /* we don't need the pipe anymore, because */
|
|
close(fd[1]); /* the children inherited them */
|
|
|
|
{ wait for children to terminate ... }
|
|
}
|
|
|
|
void
|
|
writer(void) {
|
|
/* reset the standard output to the write pipe */
|
|
dup2(STDOUT_FILENO, fd[1]);
|
|
|
|
/* we don't need the read end */
|
|
close(fd[0]);
|
|
{ exec writer process ...}
|
|
}
|
|
|
|
void
|
|
reader(void) {
|
|
/* reset the standard input to the write pipe */
|
|
dup2(STDIN_FILENO, fd[0]);
|
|
|
|
/* we don't need the write end */
|
|
close(fd[1]);
|
|
{ exec reader process ...}
|
|
}
|
|
|
|
\end{verbatim}
|
|
|
|
Recall that when a new process is forked,
|
|
it inherits all of the open files of it's parent; thus, the two
|
|
children here inherit not only standard I/O but also the pipe.
|
|
After the forks, the parent process closes the pipe and each of
|
|
the child processes closes the end of the pipe it doesn't use.
|
|
This is actually a necessary step because the kernel must know
|
|
when the reader has terminated in order to also stop the writer
|
|
(by sending \tt SIGPIPE\rm.
|
|
Since each open refNum to the read end of the
|
|
pipe is counted as a reader, any unnecessary copies must be
|
|
closed.
|
|
|
|
For further examples of implementing and
|
|
programming pipes, see the sample source code for \tt pipe.c\rm.
|
|
|
|
\section{Messages}
|
|
|
|
GNO's Message IPC is borrowed from the XINU
|
|
Operating System, designed by Douglas Comer. It is a simple way
|
|
to send a datum (a message) to another process. Messages are
|
|
32-bit (4-byte) longwords.
|
|
|
|
The Message IPC is centered around two
|
|
calls, \bf procsend\rm(2) and \bf procreceive\rm(2).
|
|
The \bf procsend \rm call sends a
|
|
message to a specified process ID. To access that message, a
|
|
process must use \bf procreceive\rm. If no message is waiting for a
|
|
process when it calls \bf procreceive\rm, the process will
|
|
\index{blocked processes} block until a message becomes available.
|
|
|
|
Since a process can only have one pending
|
|
message, the Message IPC is useful mostly in applications where
|
|
two or more cooperating processes only occasionally need to
|
|
signal each other; for example, the \bf init\rm(8) program
|
|
communicates with the \bf initd \rm
|
|
\index{daemon}
|
|
daemon by sending messages. Various
|
|
attributes are encoded in the 32-bit value sent to \bf initd\rm(8)
|
|
to instruct it on how to change its state.
|
|
|
|
If a process doesn't want to indefinitely block waiting for a message,
|
|
it can call \bf procrecvtim\rm(2). The \bf procrecvtim \rm call
|
|
accepts a timeout parameter which indicates the maximum amount of
|
|
time to wait for a message.
|
|
|
|
\section{Ports}
|
|
|
|
GNO/ME Ports IPC can be thought of as an
|
|
extended version of Messages. Whereas only one message can be
|
|
pending at once, a port can contain any number of pending
|
|
messages (up to a limit defined when an application creates a
|
|
port).
|
|
|
|
Like Messages, Ports transmit 32-bit values
|
|
between processes. The calls \bf psend\rm(2) and \bf preceive\rm(2)
|
|
work similarly to their Message counterparts.
|
|
|
|
A Port is created with the \bf pcreate\rm(2)
|
|
call. The application specifies the size of the port in this
|
|
call. When the application is done with the port, it should call
|
|
\bf pdelete\rm(2) to free up the resources used by the port.
|
|
|
|
One of the most important aspects of ports
|
|
is the ability to bind a \it name \rm to a port. Whereas many of
|
|
GNO/ME IPC mechanisms require the communicating processes to be
|
|
related in some way (common children of the same parent, for
|
|
instance) being able to give a port a name means that totally
|
|
unrelated processes can communicate. For example, the GNO/ME
|
|
print spooling system uses a named port for communicating
|
|
information about the addition of new jobs to the print queue.
|
|
The printer
|
|
\index{daemon}
|
|
daemon, \bf lpd\rm(8), creates a port with a specific
|
|
name; the name is defined by the author of the print daemon; any
|
|
application that wishes to have the daemon print a spool file
|
|
also knows this name. (The standard print daemon uses the name
|
|
``LPDPrinter''). The name allows an application to find
|
|
lpd's port regardless of the actual numeric port ID (which might
|
|
be different from system to system, or even from session to
|
|
session on the same machine).
|
|
|
|
Names are bound to ports with the \bf pbind\rm(2) call.
|
|
The numeric port ID can be obtained by passing a name to
|
|
\bf pgetport\rm(2).
|
|
|
|
\section{Pseudo-Terminals (PTYs)}
|
|
|
|
Pseudo-terminals are a bi-directional
|
|
communication channel that can be used to connect two processes
|
|
(or more correctly, a process group to another process). You may
|
|
(correctly) ask why two pipes would not do the same thing; the
|
|
answer is that a lot of modern UNIX software relies on the way
|
|
the terminal interface works, and thus would malfunction when
|
|
presented with a pipe as standard input. What PTYs provide is a
|
|
lot like two pipes, but with a TTY interface.
|
|
|
|
PTYs can be used in a number of important
|
|
and exciting applications, such as windowing systems and
|
|
'script-driven' interfaces.
|
|
|
|
Windowing systems like the UNIX X windowing system (known as just
|
|
``\bf X\rm'')
|
|
use PTYs to give a process group an interface that looks exactly
|
|
like a real terminal; however, the 'terminal' in this case is
|
|
actually a window in a graphics-based system. The program that
|
|
manages the window ('xterm' in \bf X\rm) is called the \it master\rm.
|
|
It is responsible for setting up the PTY, and starting up the
|
|
process with redirection (usually a shell) that is to run in the
|
|
window. The process running in the window is called the \it slave\rm.
|
|
|
|
\index{device!character}
|
|
To allocate a PTY, the master opens in turn
|
|
each PTY device starting with
|
|
\index{.pty}
|
|
.ptyq0. If a PTY is already in use,
|
|
the open call will return an error (the kernel uses the EXCL flag
|
|
internally). When an open succeeds, the master then has exclusive
|
|
access to that PTY. At this point, the master opens the
|
|
corresponding TTY file
|
|
\index{.tty}
|
|
(.ttyq0 --- .ttyqf), or the slave device. It
|
|
then forks off a process, which sets redirection up in the normal
|
|
fashion and then exec's the program to run on the PTY.
|
|
|
|
The following code fragment is taken from the source code for the
|
|
Graphical Shell Interface (GSI) NDA.
|
|
\tt initPipe \rm
|
|
scans the PTY devices, looking for a free one as
|
|
discussed above. Note that the master side of a PTY does \em not \rm
|
|
have (by default) a terminal interface; it is a very raw device,
|
|
with only a few \bf ioctl\rm's to be able to send signals and handle
|
|
other such low-level tasks.
|
|
|
|
\index{.pty}
|
|
\begin{verbatim}
|
|
|
|
char buffer[1024];
|
|
int ptyno, master;
|
|
|
|
int
|
|
initPipe(void)
|
|
{
|
|
int cl[2];
|
|
struct sgttyb sb;
|
|
char *ptyname = ".ptyq0";
|
|
|
|
unsigned i;
|
|
|
|
/* We have to open the master first */
|
|
for (i = 0; i<2; i++) {
|
|
/* generate a PTY name from the index */
|
|
ptyname[5] = intToHex(i);
|
|
master = open(ptyname,O_RDWR);
|
|
if (master > 0) {
|
|
break; /* successful open */
|
|
}
|
|
}
|
|
|
|
if (master < 1) {
|
|
return -1;
|
|
}
|
|
|
|
ptyno = i;
|
|
pid1 = fork(producer);
|
|
return 0;
|
|
}
|
|
\end{verbatim}
|
|
|
|
\tt producer() \rm
|
|
sets up redirection for the shell, and also opens
|
|
the slave side of the PTY. The slave processes must not have any
|
|
access whatsoever to the master side of the PTY, so \bf close(0) \rm
|
|
is used to close all open files (which includes, at this point,
|
|
the master PTY file descriptor from initPipe). Note that as in
|
|
many pipe applications, the file descriptor that will be assigned
|
|
to a newly opened file is assumed, and that can be safely done in
|
|
this case because it is clear that with no files open the next
|
|
file descriptor will be 1.
|
|
|
|
\index{.tty}
|
|
\begin{verbatim}
|
|
/* the shell is executed here */
|
|
|
|
#pragma databank 1
|
|
void
|
|
producer(void)
|
|
{
|
|
char *ptyname = ".ttyq0";
|
|
|
|
/* we must not have access to ANY other ttys */
|
|
|
|
close(0); /* close ALL open files */
|
|
ptyname[5] = intToHex(ptyno);
|
|
|
|
/* modify the tty slave name to correspond
|
|
* to the master */
|
|
|
|
slave = open(ptyname,O_RDWR); /* file descriptor 1 */
|
|
dup(slave); /* fd 2 */
|
|
dup(slave); /* fd 3 */
|
|
|
|
/* Set up the TextTools redirection */
|
|
SetOutputDevice(3,2l);
|
|
SetErrorDevice(3,3l);
|
|
SetInputDevice(3,1l);
|
|
|
|
WriteCString("Welcome to GNO GSI\r\n");
|
|
_execve(":bin:gsh","gsh -f");
|
|
|
|
/* If we get here, we were unable to run
|
|
* the shell.
|
|
*
|
|
* GDR note: printf should not be used here,
|
|
* since we're in the child process */
|
|
printf("Could not locate :bin:gsh : %d", errno);
|
|
}
|
|
#pragma databank 0
|
|
\end{verbatim}
|
|
|
|
\tt consume() \rm
|
|
is called as part of GSI's event loop. It simply
|
|
checks to see if there is any data for the master by using the
|
|
FIONREAD ioctl, one of the few ioctl's supported by the master
|
|
side. See PTY(4) for details. Any data that is available is sent
|
|
to the window via a routine toOut, which inserts the new data
|
|
into a TextEdit record.
|
|
|
|
\begin{verbatim}
|
|
void
|
|
consume(CtlRecHndl teH)
|
|
{
|
|
char ch;
|
|
int fio, fio1, i;
|
|
|
|
ioctl(master,FIONREAD,&fio);
|
|
if (fio) {
|
|
if (fio > 256) {
|
|
fio = 256;
|
|
}
|
|
fio1 = read(master,buffer,fio);
|
|
buffer[fio] = 0;
|
|
toOut(buffer,fio,teH);
|
|
updateWind1(fio,fio1);
|
|
}
|
|
}
|
|
\end{verbatim}
|
|
|
|
When the user types a key, the keypress is
|
|
sent to the slave by simply writing the data with a write call.
|
|
|
|
\begin{verbatim}
|
|
void
|
|
writedata(char k)
|
|
{
|
|
write(master, &k, 1);
|
|
}
|
|
\end{verbatim}
|
|
|
|
When the user is done with the window and
|
|
closes it, GSI closes the master end of the PTY.
|
|
|
|
\begin{verbatim}
|
|
void
|
|
closePipe(void)
|
|
{
|
|
int cl[2];
|
|
close(master);
|
|
}
|
|
\end{verbatim}
|
|
|
|
When this is done, the slave process
|
|
receives a SIGHUP signal, to indicate that the connection was
|
|
lost. Since the standard behavior of SIGHUP is to terminate the
|
|
process, the slave dies and either the slave or the kernel closes
|
|
the slave end. At this point, the PTY is available for re-use by
|
|
another application.
|
|
|
|
As you can see, PTYs are very simple to
|
|
program and use. The simplicity can be misleading, for PTYs are a
|
|
very powerful method of IPC. As another example of the use of
|
|
PTYs, we point out that PTYs can be used to drive programs with
|
|
'scripts'. These scripts are a series of 'wait-for' and 'print'
|
|
operations, much like auto-logon macros in communications
|
|
programs such as ProTERM. Script-driving a program can be used to
|
|
automate testing or use of an application.
|
|
|
|
PTYs can be used to test software that
|
|
would normally work over a regular terminal (such as a modem).
|
|
Since PTYs are identical (to the slave) to terminals, the
|
|
application being tested doesn't know the difference. What this
|
|
means to the programmer is incredible power and flexibility in
|
|
testing the application. For example, a communications program
|
|
could be nearly completely tested without ever dialing to another
|
|
computer with a modem!
|
|
|
|
There are so many applications of PTYs that
|
|
to attempt to discuss them all here would be impossible; as PTYs
|
|
are discovered by more GNO/ME programmers we expect that more
|
|
useful PTY applications will become available.
|
|
|
|
\section{Deadlock}
|
|
|
|
\index{deadlock|(}
|
|
With interprocess communication comes the
|
|
problem of \em deadlock\rm. If a situation arises where two or
|
|
more processes are all waiting for an signal from one of the
|
|
other waiting processes, the processes are said to be deadlocked.
|
|
|
|
The best way to explain deadlock is to give
|
|
an example. Suppose that two processes are connected with two
|
|
pipes so that they can communicate bidirectionally. Also suppose
|
|
that each of the pipes are full, and that when each process
|
|
writes into one of the pipes they are blocked.
|
|
\index{blocked processes}
|
|
Both processes are blocked waiting for the other to unblock them.
|
|
|
|
There is no way for the operating system to
|
|
detect every conceivable deadlock condition without expending
|
|
large amounts of CPU time. Thus, the only way to recover from a
|
|
deadlock is to kill the processes in question. Responsibility for
|
|
preventing deadlock situations is placed on the programmer.
|
|
Fortunately, situations where deadlock can occur are infrequent;
|
|
however, you should keep an eye out for them and try to work
|
|
around them when they do occur.
|
|
|
|
\index{deadlock|)}
|
|
|
|
\appendix
|
|
|
|
%
|
|
% Appendix: Making System Calls
|
|
%
|
|
|
|
\begin{latexonly}
|
|
\chapter{Making System Calls}
|
|
\end{latexonly}
|
|
\begin{htmlonly}
|
|
\chapter{Appendix A: Making System Calls}
|
|
\end{htmlonly}
|
|
|
|
\begin{latexonly}
|
|
\end{latexonly}
|
|
\begin{htmlonly}
|
|
\end{htmlonly}
|
|
|
|
The GNO Kernel is accessed through system
|
|
calls. The actual procedure is very simple from C: simply
|
|
\#include the appropriate header file as noted in the synopsis of
|
|
the call's manual page, and call it as you would any other C
|
|
function. From
|
|
\index{assembly language programs}
|
|
assembly language the procedure is no more
|
|
difficult, using the advanced macros provided for the \index{APW} APW and
|
|
ORCA assemblers. Make sure, however, that you have defined a word
|
|
variable \bf errno\rm. Lowercase is important, use the 'case on'
|
|
and 'case off' directives to ensure that the definition of \bf errno \rm
|
|
is case-sensitive. The system call interface libraries store any
|
|
error codes returned by the kernel in this variable.
|
|
|
|
If you are going to be accessing the kernel
|
|
from a language other than those for which interfaces are
|
|
provided, then the following information is for you.
|
|
|
|
\section{System Call Interface}
|
|
|
|
The system calls are implemented as a user toolset, tool number 3.
|
|
These tools are called the same way regular system tools (such as QuickDraw)
|
|
are called, except that you must \tt JSL \rm to \bf \$E10008 \rm
|
|
instead of to \bf \$E10000 \rm (or to \bf \$E1000C \rm instead of
|
|
to \bf \$E10004 \rm for the alternate entry point). The function
|
|
numbers for the currently defined tools are as follows:
|
|
|
|
\index{alarm}
|
|
\index{alarm10}
|
|
\begin{tabular}{llll}
|
|
getpid * & \$0903 &
|
|
kill & \$0A03 \\
|
|
fork & \$0B03 &
|
|
swait & \$0D03 \\
|
|
ssignal & \$0E03 &
|
|
screate & \$0F03 \\
|
|
sdelete & \$1003 &
|
|
kvm\_{}open & \$1103 \\
|
|
kvm\_{}close & \$1203 &
|
|
kvm\_{}getproc & \$1303 \\
|
|
kvm\_{}nextproc & \$1403 &
|
|
kvm\_{}setproc & \$1503 \\
|
|
signal & \$1603 &
|
|
wait & \$1703 \\
|
|
tcnewpgrp & \$1803 &
|
|
settpgrp & \$1903 \\
|
|
tctpgrp & \$1A03 &
|
|
sigsetmask & \$1B03 \\
|
|
sigblock & \$1C03 &
|
|
execve & \$1D03 \\
|
|
alarm & \$1E03 &
|
|
setdebug * & \$1F03 \\
|
|
setsystemvector * & \$2003 &
|
|
sigpause & \$2103 \\
|
|
dup & \$2203 &
|
|
dup2 & \$2303 \\
|
|
pipe & \$2403 &
|
|
getpgrp & \$2503 \\
|
|
ioctl & \$2603 &
|
|
stat & \$2703 \\
|
|
fstat & \$2803 &
|
|
lstat & \$2903 \\
|
|
getuid & \$2A03 &
|
|
getgid & \$2B03 \\
|
|
geteuid & \$2C03 &
|
|
getegid & \$2D03 \\
|
|
setuid & \$2E03 &
|
|
setgid & \$2F03 \\
|
|
procsend & \$3003 &
|
|
procreceive & \$3103 \\
|
|
procrecvclr & \$3203 &
|
|
procrecvtim & \$3303 \\
|
|
setpgrp & \$3403 &
|
|
times & \$3503 \\
|
|
pcreate & \$3603 &
|
|
psend & \$3703 \\
|
|
preceive & \$3803 &
|
|
pdelete & \$3903 \\
|
|
preset & \$3A03 &
|
|
pbind & \$3B03 \\
|
|
pgetport & \$3C03 &
|
|
pgetcount & \$3D03 \\
|
|
scount & \$3E03 &
|
|
fork2 & \$3F03 \\
|
|
getppid & \$4003 &
|
|
SetGNOQuitRec & \$4103 \\
|
|
alarm10 & \$4203 \\
|
|
\end{tabular}
|
|
|
|
The following system calls are new to GNO v2.0.6:
|
|
|
|
\begin{tabular}{llll}
|
|
select & \$4303 &
|
|
InstallNetDriver & \$4403 \\
|
|
socket & \$4503 &
|
|
bind & \$4603 \\
|
|
connect & \$4703 &
|
|
listen & \$4803 \\
|
|
accept & \$4903 &
|
|
recvfrom & \$4A03 \\
|
|
sendto & \$4B03 &
|
|
recv & \$4C03 \\
|
|
send & \$4D03 &
|
|
getpeername & \$4E03 \\
|
|
getsockname & \$4F03 &
|
|
getsockopt & \$5003 \\
|
|
setsockopt & \$5103 &
|
|
shutdown & \$5203 \\
|
|
setreuid & \$5303 &
|
|
setregid & \$5403 \\
|
|
\end{tabular}
|
|
|
|
Parameters should be pushed onto the stack
|
|
in the same order as defined by the C prototypes outlines in the
|
|
synopsis section of the manual pages; that is, left-to-right. In
|
|
addition to those parameters, all of the functions (except those
|
|
denoted by a \bf *\rm) take an integer pointer parameter \bf errno\rm.
|
|
This is a pointer to a word value which will contain the \bf errno \rm
|
|
code returned by the function if an error occurs, and should be
|
|
pushed onto the stack after all the other parameters. The calls
|
|
do not clear this code to 0 if no error occurs; thus, you must
|
|
check the return value of the function to see if an error
|
|
occurred, and then check errno to get the actual error code.
|
|
|
|
Do not forget to also push space on the
|
|
stack (before the parameters) for the call to store its return
|
|
value.
|
|
|
|
These low-level system call interfaces are
|
|
not to be used in general programming. It is assumed the
|
|
programmer will use the libraries provided, or use this
|
|
information to create a new library. The system call interface is
|
|
subject to change without notice; any changes will, of course, be
|
|
documented in future versions of GNO/ME.
|
|
|
|
\section{System Call Error Codes}
|
|
|
|
The following codes are taken from \tt <sys/errno.h>\rm. The
|
|
codes up to EPERM are the same values as those defined by ORCA/C
|
|
for compatibility reasons. Error conditions are usually reported
|
|
by system calls by returning a -1 (word) or NULL (long) value.
|
|
Which error codes can be expected from a particular call are
|
|
detailed in the errors section in the appropriate manual page.
|
|
|
|
\begin{description}
|
|
\item[EDOM]
|
|
Domain error. Basically an undefined error code.
|
|
\item[ERANGE]
|
|
Range error. A value passed to a system call was too large,
|
|
too small, or illegal.
|
|
\item[ENOMEM]
|
|
Not enough memory. The kernel could not allocate enough
|
|
memory to complete the requested operation.
|
|
\item[ENOENT]
|
|
No such file or directory. The file specified could not be found.
|
|
\item[EIO]
|
|
I/O error. An error occurred trying to perform an I/O operation,
|
|
such as that caused by bad media. It also refers to a disk
|
|
error not covered by the other errno codes.
|
|
\item[EINVAL]
|
|
Invalid argument. An argument to a system call was invalid in some way.
|
|
\item[EBADF]
|
|
Bad file descriptor. The file descriptor passed to the kernel does not
|
|
represent an open file.
|
|
\item[EMFILE]
|
|
Too many files are open. The kernel cannot open any more files
|
|
for this process; it's open file table is full. Close some other
|
|
open files and retry the operation.
|
|
\item[EACCESS]
|
|
Access bits prevent the operation. One of the access bit settings
|
|
(delete, rename, read, write) associated with the file does not allow
|
|
the requested operation.
|
|
\item[EEXIST]
|
|
The file exists. An attempt to create a new file with the same name
|
|
as an existing file results in this error.
|
|
\item[ENOSPC]
|
|
No space on device. There is not enough room on the requested
|
|
device to complete the operation. This is usually indicative
|
|
of a full disk.
|
|
\item[EPERM]
|
|
Not owner. Not yet used in GNO.
|
|
\item[ESRCH]
|
|
No such process. The process ID specified does not refer to an active
|
|
process. Possibly the process terminated earlier.
|
|
\item[EINTR]
|
|
Interrupted system call. Certain system calls can be interrupted by
|
|
signals. In cases where the user has specified that those calls not be
|
|
automatically restarted, the call will return this error.
|
|
\item[E2BIG]
|
|
Arg list too long. Too many arguments were specified in an
|
|
\bf \_{}execve\rm(2) call.
|
|
\item[ENOEXEC]
|
|
Exec format error. The file specified is not in an executable format
|
|
(OMF load file).
|
|
\item[ECHILD]
|
|
No children. This error is returned by \bf wait\rm(2) when there
|
|
are no child processes left running.
|
|
\item[EAGAIN]
|
|
No more processes. The process table is full, the \bf fork\rm(2)
|
|
cannot complete.
|
|
\item[ENOTDIR]
|
|
Not a directory. One of the elements in a pathname refers to a file
|
|
which is not a directory.
|
|
\item[ENOTTY]
|
|
Not a terminal. The file descriptor passed to an \bf ioctl\rm(2)
|
|
or job control call does not refer to a terminal file.
|
|
\item[EPIPE]
|
|
Broken pipe. If a process attempts to write on a pipe with no
|
|
readers, and has blocked or ignored SIGPIPE, this error is
|
|
returned by the write operation.
|
|
\item[ESPIPE]
|
|
Illegal seek. Similar to ENOTBLK, but specific for pipes.
|
|
\item[ENOTBLK]
|
|
Not a block device. An attempt to perform an operation on a character
|
|
device that only makes sense on a block device.
|
|
\end{description}
|
|
|
|
|
|
|
|
\section{System Panics}
|
|
|
|
In most cases, if the kernel detects an
|
|
error in operation an appropriate error code is returned by the
|
|
function in question (GS/OS calls, ToolBox calls, or system calls
|
|
as described above). However, there are rare circumstances where
|
|
the kernel detects what should be an impossible condition. This
|
|
can happen due to bugs in the kernel, because the kernel was
|
|
overwritten by a buggy program, or for any number of other
|
|
reasons.
|
|
|
|
When the kernel does come across such an
|
|
error, system operation cannot continue and what ensues is called
|
|
a \em system panic\rm. Panics are very easily noticed- the kernel
|
|
will print an error message on the screen and ensure that the
|
|
text screen is visible, turning off any graphics mode if
|
|
necessary. The kernel then sets the text and background colors to
|
|
red on white - a very noticeable condition. At that point, the
|
|
kernel turns off
|
|
\index{context switch}
|
|
context switching to prevent any background
|
|
process or other interrupt driven code from further confusing the
|
|
system. This is done mainly to prevent damage to disk directory
|
|
structures by a bad system.
|
|
|
|
When a system panic does occur, the only
|
|
thing you can do is reboot your system. If you can reliably
|
|
reproduce a system panic, please record the panic message and the
|
|
sequence of events necessary to evoke the panic and report the
|
|
information to Procyon, Inc.
|
|
|
|
%
|
|
% Appendix: Miscellaneous Programming Issues
|
|
%
|
|
|
|
\begin{latexonly}
|
|
\chapter{Miscellaneous Programming Issues}
|
|
\end{latexonly}
|
|
\begin{htmlonly}
|
|
\chapter{Appendix B: Miscellaneous Programming Issues}
|
|
\end{htmlonly}
|
|
|
|
\section{Option Arguments}
|
|
|
|
The Free Software Foundation (also known as the
|
|
FSF), invented user friendly long format option arguments, and
|
|
defined the ``\bf +\rm>'' character for interpretation
|
|
that a long format follows. This interpretation is generally
|
|
followed in the UNIX community. There are two files which will assist
|
|
you in programming GNO/ME utilities with both short and long
|
|
format options, \tt <getopt.h> \rm for short options, and
|
|
\tt <getopt1.h> \rm for long options.
|
|
|
|
\section{Pathname Expansion}
|
|
|
|
Those of you familiar with programming in
|
|
the ORCA environment should be familiar with the shell calls
|
|
\tt InitWildcard \rm and \tt NextWildcard\rm.
|
|
These shell calls, while supported by \bf gsh\rm,
|
|
are no longer necessary. All shell utilities that work with
|
|
multiple filenames do not need to provide support for file
|
|
globbing, as this is taken care of transparently to the command.
|
|
|
|
%
|
|
% Glossary
|
|
%
|
|
|
|
\chapter{Glossary}
|
|
|
|
\begin{description}
|
|
\item[Asynchronous]
|
|
An event that may take place at any time. See synchronous.
|
|
\item[BASIC]
|
|
\index{BASIC}
|
|
Beginners All-purpose Symbolic Instruction Code. A simple computer
|
|
language.
|
|
\item[Blocked]
|
|
\index{blocked processes}
|
|
Refers to a process waiting for some event to occur. Processes can
|
|
block on terminal I/O, signals, and other IPC and I/O functions.
|
|
\item[Console]
|
|
The terminal which represents the IIGS's keyboard and monitor.
|
|
\item[Context]
|
|
The attributes which define the state of a process. This includes
|
|
the program counter, stack pointer, and other machine registers (both
|
|
CPU and other computer hardware).
|
|
\item[Controlling terminal]
|
|
\index{controlling terminal}
|
|
The terminal which ``controls'' a process or process group;
|
|
processes can receive keyboard signals (such as SIGTSTP, or
|
|
\index{\^{}Z} \^{}Z)
|
|
only from their controlling terminal.
|
|
\item[Critical Section]
|
|
A piece of code inside which only one process at a time may
|
|
be allowed to execute. Critical sections are usually protected by
|
|
semaphores.
|
|
\item[Daemon]
|
|
\index{daemon}
|
|
A process that runs in the \index{background} background and
|
|
waits to act on an
|
|
asynchronous event. These can be anything: waiting for a caller
|
|
on a modem, waiting for spooled files to print, etc. Daemons
|
|
are usually started at boot time by the \bf initd\rm(8)
|
|
process.
|
|
\item[Deadlock]
|
|
\index{deadlock}
|
|
A situation where two or more communicating processes are blocked,
|
|
waiting on each other. See Chapter 5, ``Deadlock''.
|
|
\item[Errno]
|
|
A variable which holds a descriptive numeric error code,
|
|
returned from C libraries and system calls.
|
|
\item[Foobar, foo, bar]
|
|
Foobar derives from an old military acronym FUBAR. In it's politest
|
|
interpretation it stands for Fouled Up Beyond All Recognition.
|
|
Computer scientists borrowed the term and created foobar.
|
|
When a name for an object in a code fragment is needed but the
|
|
name itself is not important, foo and bar are first choice among
|
|
computing science types. They should not be used in production
|
|
code.
|
|
\item[Executable]
|
|
A program as it resides on disk. Executables can be compiled or
|
|
assembled programs, or shell scripts. Executables are run by
|
|
typing their name on the shell's command line and frequently take
|
|
paramters to determine what data they operate on and particulars
|
|
of how they do it.
|
|
\item[GNO/ME]
|
|
GNO Multitasking Environment. The complete package including the GNO
|
|
kernel and the GNO Shell.
|
|
\item[GNO Kernel]
|
|
Heart of GNO/ME. Executes processes when asked by the GNO Shell.
|
|
\item[GNO Shell]
|
|
Provides an interface between the user and the GNO kernel.
|
|
\item[gsh]
|
|
GNO Implementation of a UNIX-like shell.
|
|
\item[GS/OS]
|
|
A 16 bit Operating System for the Apple IIgs.
|
|
\item[IPC]
|
|
``Inter-Process Communication''. Any method by which processes
|
|
can pass information to other processes.
|
|
\item[Job]
|
|
\index{controlling terminal}
|
|
A set of related processes. Jobs are generally composed of
|
|
processes with a common parent and the same controlling terminal.
|
|
\item[Manpage]
|
|
Refers to the system call and utility documentation provided with GNO.
|
|
Manpages exist on disk as either \bf nroff\rm(1) or \bf aroff\rm(1)
|
|
source. They can also be preformatted by \bf catman\rm(1). They
|
|
can be viewed by various utilites on a variety of output devices.
|
|
\item[Master]
|
|
\index{.pty}
|
|
Refers to the .PTYxx side of a pseudo-terminal, and also
|
|
the process controlling that device. The master is usually responsible
|
|
for setting up the PTY and running a process on it.
|
|
\item[Message]
|
|
A 32-bit value that is passed via the Messages IPC mechanism to
|
|
another process.
|
|
\item[Mutex]
|
|
\index{critical section}
|
|
Short for mutual exclusion, a term that refers to protecting a
|
|
critical section.
|
|
\item[Panic]
|
|
An unrecoverable kernel error, usually indicating that an
|
|
internal data structure has become corrupted.
|
|
\item[Parent]
|
|
When talking about a process, the parent of a process is the one that
|
|
spawned it; i.e., made the \bf fork\rm(2) system call.
|
|
\item[Pipe]
|
|
A unidirectional IPC mechanism. Pipes transmit binary 8-bit data.
|
|
\item[Pipeline]
|
|
Two or more processes connected by pipes.
|
|
\item[Port]
|
|
A flow-controlled IPC mechanism that can pass longwords of data.
|
|
\item[Process]
|
|
A program in execution.
|
|
\item[Process Group]
|
|
An identifying code for a job. Process groups are also assigned
|
|
to TTYs, which allows the TTY to differentiate \index{background}
|
|
background jobs from foreground jobs when sending interrupt signals.
|
|
\item[Pseudo-terminal]
|
|
A bidirectional communications channel, normally used in windowing
|
|
systems or for advanced control and testing applications.
|
|
\item[PTY]
|
|
See 'pseudo-terminal'.
|
|
\item[Semaphore]
|
|
A data object used to synchronize concurrent processes.
|
|
\item[Sequentialization]
|
|
\index{critical section}
|
|
The task of ensuring that critical sections are only executed by one
|
|
concurrent process at a time.
|
|
\item[Signal]
|
|
A software interrupt and IPC mechanism.
|
|
\item[Slave]
|
|
1. A good term to describe the relationship of Joe Citizen to the IRS.
|
|
2. The \index{.tty} .TTYxx side of a pseudo-terminal; the slave
|
|
is usually an application program of some kind, like a shell.
|
|
\item[Suspended]
|
|
Refers to a process whose execution has been stopped.
|
|
\item[Synchronous]
|
|
An event that takes place at a predetermined time or sequence of times.
|
|
Also used to indicate the act of waiting for an event to happen. See
|
|
asynchronous.
|
|
\item[Terminal]
|
|
Any device that looks like a terminal; this includes pseudo-ttys. By
|
|
definition, a terminal supports all of the \bf tty\rm(4)
|
|
ioctl calls.
|
|
\item[Tty]
|
|
Short for Teletype. TTY is an anachronistic term; in modern usage
|
|
it is taken to mean ``terminal''.
|
|
\item[UNIX]
|
|
Popular operating system which has growing use in education and
|
|
business. One of the first operating systems to support multitasking.
|
|
\end{description}
|
|
|
|
\begin{comment}
|
|
\printindex
|
|
\end{comment}
|
|
|
|
\chapter{Index}
|
|
|
|
Sorry, the index is not yet complete. Stay tuned ...
|
|
|
|
\end{document}
|
|
|