You are on page 1of 4

DOS-C Architecture

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.

The kernel is written in C wherever possible. However, certain functions are


written in assembly language for either efficiency or necessity. These
functions typically perform direct machine control, such as stack
manipulation and flipping interrupt bits. You will find this code in a number
of assembly files along with C to assembly interface functions.

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.

DOS-C File System


The DOS-C design allows for a file manager that is independent from the
design of the rest of the operating system. The fs module is the DOS-C file
manager. Whenever an application requests an operation on a file resident on
a block device, fs performs the operation. It does this by working with an
internal table, called the fnode (or file node) table.

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.

DOS-C Memory Management

Memory management in DOS-C closely emulates MS-DOS. Since DOS-C


is a real mode operating system, the DOS-C memory manager is much
simpler than what you'll find in other protected mode 80X86 operating
systems. In a manner similar to the MS-DOS, DOS-C manages memory
through the use of a memory block linked list that utilizes the same arena
header as the one MS-DOS uses.

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

Because DOS-C design is designed to emulate MS-DOS, it should be of


little surprise that the operating system is not multitasking. As a result, the
task manager, task, manages a single user task. Its primary function is to act
as a task loader, unlike other operating systems where task loading is an
incidental to managing the task. Also, there are only two relatively simple
executable file types, .COM and .EXE.

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.

Both loaders initially allocate memory from memmgr to place the


environment strings in. The differences begin when the actual file loading
occurs. The .COM loader merely allocates memory and begins loading the
file into memory for a maximum of 64K. The .EXE loader, on the other
hand, computes the size required and then allocates memory. It then
proceeds to load the image. When task completes loading the image, it does
a seek to the relocation offset and does a segment fixup (necessary for the
segmented architecture of the 80X86 family). From this point, both loaders
proceed with creating the PSP, cloning the file table, initializing the task's
registers and executing the task if so requested.

DOS-C Device Driver Interface Layer and Device Drivers

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.

(c) Copyright 1997 by Pasquale J. Villani


All Rights Reserved.

You might also like