Professional Documents
Culture Documents
The DOS-C architecture is a layered one similar to what you'll find in other
operating systems. The only difference between DOS-C and other
monolithic operating systems is that there is a decoupling between the upper
and lower layers of the operating system. To guarantee that DOS-C is MS-
DOS compatible, there are two interface layers where full compliance is
necessary. The first interface layer is the DOS API. This is the set of entry
points that you expect from a DOS compatible operating system. These
include the traditional INT 20h, 21h, 22h, 23h, 24h, 27h, 28h and 2Fh. The
other interface layer is the device driver interface. This layer is also well
documented and supported by many hardware and software vendors. This
layer allows DOS-C to be compatible with MS-DOS to assure proper
support of loadable device drivers.
DOS-C API
A DOS API entry point handler intercepts any system call to DOS-C and
translates it into a C call. We do this as close to the entry point as possible in
order to use C as early as possible. The C call then does some context
switching and performs a call to the appropriate internal service function. It
is up to the service routine to dispatch the system call through the kernel to
the appropriate handler.
The dispatcher directs a system call into the kernel. A large number of calls
are directed into the dosfns, or DOS Functions, layer. This layer works with
the lower layers to add the DOS appearance to the system calls. It does this
by combining calls into the various managers in the next lower layers with
code to add features to the manager calls that are unique to a DOS interface.
For example, this layer contains functions that encompass all rules for
handling file I/O that deals with PSP, handles or character and block I/O
functionality.
The fnode table is the foundation for the design of the FAT file system
manager. The fnode data structure controls all internal file operations and
virtualizes the file. When fs performs an operation such as create or open, it
allocates an entry from the fnode table and populates the fnode fields. The
call returns a number that is the index into the fnode table. From here on out,
any function that performs an operation on the file receives this number. The
fnode table entry that corresponds to this index controls all file parameters.
If you are familiar with DOS internals from the undocumented internals
books and articles, you will recognize the need to map internal fnode to the
SFT (System File Table) structure used by DOS. We handle this through the
dosfns layer function. The module dosfns maps the fnode number to an SFT
handle, which is part its "DOS personality" responsibility. At the fs level, it
does its work in an "OS neutral" mode in order to localize unique features to
the personality module.
The arena header in DOS-C is known as the MCB (Memory Control Block).
As with MS-DOS, this data structure is in front of each allocated and free
memory block. DOS-C uses the same 'M' and 'Z' signatures to identify the
block type. Also, the segment value of the PSP of the program it belongs to
or a 0008h if it belongs to DOS-C, identifies the owner of the block in the
same way. DOS-C uses all other entries in an identical manner. Many
applications make use of this information and DOS-C provides this same
information for sake of compatibility. Unlike fs where MS-DOS personality
splits between it and dosfns, memmgr contains all DOS personality.
DOS-C Task Management
Both executable file types start from a single load entry. It is up to DOS-C to
identify which file type it is. It does this by examining the first two bytes of
the file. If it is an 'MZ', then it is an .EXE file and task invokes the .EXE
loader, otherwise task assumes it to be a .COM binary image and task
invokes the .COM loader.
At the bottom of the DOS-C architecture, but just above the device drivers,
is the device driver interface layer. There are two handlers in this layer,
chario and blockio. Although each handler uses different methods, both
handlers are the primary interface between the device drivers and the
remainder of the kernel. Both handlers perform all the necessary buffer
management for both types of I/O, including line buffer management.
Both I/O handlers are loosely based on the UNIX I/O model. As with UNIX,
there are two types of I/O handlers. The first type is the character I/O type.
This type of I/O appears as a stream of bytes to the kernel. The kernel either
sequentially reads a byte from or writes a byte to a device driver. There are
also functions to read a buffer into memory and handle the familiar DOS line
editing functions.
The block I/O interface provides functions to read and write a block of data
to a block device -- usually a disk. Each block corresponds to a sector and is
represented in memory as a data structure in a block cache. When the kernel
reads data from a disk, blockio reads the sector into a buffer and places it
into a Least Recently Used (LRU) chain. When blockio needs a new buffer,
it writes the tail of the list to disk, if needed, and returns that buffer. When
blockio completes the data transfer, the buffer goes to the head of the LRU
chain, indicating that it is the newest buffer. Management functions handle
these operations for dirty buffer write back, as well as buffer fill. There are
also buffer management functions to perform operations such as LRU
management and flush.
As with the API, the device driver interface is well documented. Since the
interface is designed for an assembly language system, a special assembly
language function interfaces all device drivers. This function, execrh,
accepts a request packet from the I/O handlers that contains a function
number requested by the device driver. It handles the correct sequence of
calls to the strategy and interrupt entry points for the device driver and
returns the packet to the I/O handler.
The DOS-C device drivers are the bottom layer of the kernel. Like the
remainder of the kernel, C is used in these device drivers also. The device
drivers perform the necessary device interface between the kernel and the
device itself. DOS-C has the same device drivers as MS-DOS and they
perform the same functions as their MS-DOS counterparts.