Guide to Multitasking Operating Systems:Overview of the OS/2 Operating System
This section covers, in depth, the concepts brought forth in the previous section Fundamentals of Operating Systems with respect to the OS/2 operating system.
Introduction to OS/2
OS/2 Process Management
This topic deals with how OS/2 multitasks, or runs many threads of execution at the same time.
Introduction to OS/2 Process Management
In any multitasking operating system, the hardware is managed as shared resources to be distributed among concurrently executing entities. The architecture that describes how these concurrent entities are created, terminated, and managed is called the tasking or multitasking model. The multitasking model describes how resources-such as the processor, memory, files, devices, and interprocess communication structures-are shared in the OS/2 system.
Perhaps the most important resource that is shared in a multitasking environment is the processor. The operating system shares the processor among concurrently executing entities using a technique known as time-slicing. An operating system that provides timeslicing switching between programs. enabling each program to run for a short period of time called a time-slice or quanta. This technique results in the processor resource being shared among the programs.
The OS/2 multitasking model consists of a hierarchy of multitasking objects called sessions, processes, and threads The session is at the top of the hierarchy, and the thread is at the bottom. The session is the unit of user I/O device sharing. Processes are analogous to programs, and are the unit of sharing for such resources such as memory, files, semaphores, queues, and threads. A thread is the basic unit of execution, and a single process may have multiple threads that execute concurrently within it.
OS/2 Sessions
Each session contains a logical video buffer, logical keyboard, logical mouse, and one or more processes that are said to be running in or attached to the session. The logical devices are per-session representations of the physical devices. Processes running in the session perform their user I/O in the session's logical devices. Only one session at a time has its logical devices mapped onto the physical devices; this session is called the foreground session. The other sessions are in the background. Users can change the current foreground session by issuing the commands to switch between sessions with a keyboard or a mouse. Sessions are used to provide an infrastructure for program management and user I/O device sharing.
You can think of the session as providing a virtual personal computer to certain groups of processes as OS/2 maintains: a logical video buffer which is a shadow of the screen contents, a keyboard input queue, and a mouse event queue. Processes running in sessions see a dedicated keyboard, video buffer, and mouse to which API calls can be made at any time.
OS/2 Processes
A process is the basic unit of programming and resource sharing in OS/2. A process corresponds to a program and is created when a program is loaded. A process is the central abstraction for the sharing of resources, such as processors, memory, files, and interprocess communication data structures. Each process is assigned a unique process identifier(PID) by the kernel. OS/2 1.X provides support for up to 255 processes; OS/2 2.0 provides support for up to 4095 processes.
The system maintains many resources on a per-process basis. The primary resources contained in a process are the memory domain and the threads of execution. A thread provides a sequence of instructions with an instance of execution. All proceesses are created with one thread and have the capability of creating more threads. The threads within a process all share the processes resources and have access to one another. Although memory and threads are the main features within a process, the system also tracks many other resources on a process basis, such as signal handlers, open files, and interprocess communication features such as semaphores, queues, and pipes.
OS/2 Threads
Threads are the dispatchable units within an OS/2 process, In other words, processes really do not run, but threads do. A thread provides within a process a piece of code with an execution instance. Each process in the system has at least one thread. From the user's perspective, a thread's context consists of a register set, a stack, and an execution priority.
Threads share all the resources owned by the process that creates them. All the threads within a process share the same virtual address space, open file handles, semaphores, and queues. Each thread is in one of three states: running, ready to run, or blocked. Only a single thread in the system is actually in the running state on uni-processor harware platforms. The running thread is the ready-to-run thread that is currently selected to run according to the OS/2 priority scheme. Threads that are in the blocked state are awaiting the completion of an event.
When OS/2 switches between threads, it automatically saves the context of the current running thread and restores the context of another thread that is ready to run. This is called a context switch.
There are several advantages to a multi-thread process model over the traditional single-thread process model found in many systems such as UNIX. Since threads share the process's resources, thread creation is far less expensive than process creation, and threads within a process enjoy a tightly coupled environment. When a thread is created, the system doesn't have to create a new virtual address space or load a program file, resulting in an inexpensive concurrent execution path.
OS/2 Scheduling
All threads in the system compete for processor time. To determine which threads should run, OS/2 implements a multilevel priority architecture with dynamic priority variation and round robin scheduling within a priority level. Each thread has its own execution priority, and high-priority threads that are ready to run are dispatched before low-priority threads that are ready to run.
There are four priority classes in the OS/2 system: time critical, server, regular, and idle. The server class is also called the fixed-high priority class. Each priority class is further divided into 31 priority levels.
Threads in the highest, or time-critical, priority class, have timing constraints. An example of a time-critical thread is a thread that waits for data to come from a device driver monitoring a high speed communications device. The system guarantees that there is a maximum interrupt disable time of 400 microseconds, and that time-critical threads are dispatched within 6 milliseconds of becoming ready to run. These timing criteria ensure that the system can respond rapidly to the needs of time-critical threads, and also be flexible enough to allow a user to switch between programs quickly. Most threads in the system, however, are in the regular priority class.
The server priority class is used for programs that run on a server environment that need to execute before regular priority class programs on the server. The server class ensures that client programs relying on the server do not suffer performance degradation due to a regular class program running locally on the server itself.
Threads in the idle priority class will run only when there is nothing to run in time-critical, server, or regular priority class. Typically, idle-class threads are daemon threads that run in the background. A daemon thread is one that intermittently awakens to perform some chores, and then goes back to being blocked.
The scheduling algorithm is round-robin within the same priority level. For example, if five threads have the sam priority, the system will run each of the five, one after another, by giving each one a timeslice. The timeslicing is driven by a system clock, and the user can configure the timeslices from 32 to 248 milliseconds by using TIMESLICE in the CONFIG.SYS file. A thread runs for its entire timeslice unless an interrupt occurs that results in making another thread of a higher priority class ready to run. In such cases, the running thread is preempted. Otherwise, a thread runs for the length of its timeslice, unless it calls the kernel and blocks.
OS/2 Process Coordination
Interprocess Communication is a corollary of multitasking. Now that PC's can have more than one program running at the same time, there will be most likely be a need for those programs to exchange information and commands. OS/2 provide s the facilities for separate programs, each running in their own address space, to communicate information through system supported interprocess communication protocols(IPC's). Some of the IPC's can operate across machine boundaries and are key to the development of LAN-based client-server applications. OS/2 provides a rich set of IPC's. These include: Anonymous Pipes, Named Pipes, Queues, and Shared Memory.
An Anonymous Pipe is a fixed length circular buffer in memory that ca n be accessed like a file of serial characters through a write handle and a read handle(handles are pointers into the file). Anonymous pipes are used mostly by parent processes to communicate with their descendants by passing the pipe handles through inheritance.
Named Pipes provide two-way communications among unrelated processes either locally or remotely. The server side of an OS/2 process creates the pipe and waits for the clients to access it. Clients use the standard OS/2 file services to gain access to the named pipe. Multiple clients can be serviced concurrently over the same pipe.
A Queue allows byte stream packets written by multiple processes to be read by a single process. The exchange does not have to be synchronized. The receiving process can order the access to the packets or messages in one of three modes: first-in/first-out(FIFO), last-in/first-out (LIFO), or priority. Items can be retrieved from the queue either sequentially or by random access. The OS/2 queues contain pointers to messages, as opposed to a copy of the data itself. Shared Memory is another interprocess communication protocol. OS/2 provides facilities for the creation of named shared segments. Any process that knows the named memory object has automatic access to it. Processes must coordinate their access to shared memory through the use of synchronization techniques.
Interprocess Synchronization. Interprocess synchronization is another corollary of multitasking. It consists of the mechanisms for keeping concurrent processes for threads from interfering with one another when accessing shared resources. The idea is to serialize the access to the shared resource by using a protocol that all parties agree to follow. OS/2, like most operating systems, provides an atomic service called the the semaphore which applications may use to synchronize their actions.
OS/2 Memory Management
This topic deals with how OS/2 manages memory.
Introduction to OS/2 Memory Management
Memory management is the way in which an operating system allows applications to access the system's memory, either for private use by a single application or to be shared between applications. In either case, it is the responsibility of the operating system's memory management component to supervise the correct use of memory and to ensure that no application gains access to memory outside its own address space. It also includes the way in which memory is allocated. The operating system must check how much memory is available to applications, and handle the situation when there is no longer any real memory left to satisfy an application's requests.
Previous versions of OS/2 were based upon the Intel 80286 processor architecture. In this architecture, there is a limitation on the amount of memory that can be addressed as a single unit. This is due to the fact that memory is managed in segments of up to 64KB in size. Previous versions maintained a series of descriptor tables for memory segments, and 16 bits were allocated in each table entry for the length of the segment. Thus, each descriptor table entry gave access of up to 2^16 = 64KB in size. If the need arose for more than 64KB to be used for a single memory object or data structure, the programmer and the operating system had to take this limitation into consideration, and implement appropriate algorithms to use multiple memory segments for a single logical structure.
OS/2 2.0, however, is based upon the Intel 80386 processor architecture. This processor has a 32-bit addressing scheme in place of the 24-bit overlapped scheme used in the 80286, thereby giving access to 2^32 = 4GB of memory in a single logical unit.
In the 80386 architecture, memory is split into fixed size units of 4KB. All memory allocation, addressing, swapping, and protection is based on pages. As with previous versions of OS/2, the total memory, allocated to all processes running in the system, may exceed the physical memory available. Memory objects or parts of memory objects, which are not reuired by the currently executing process, may be temporarily migrated out to secondary storage(disk). When used with a paged memory management scheme, this procedure is known as paging. An application may request a large amount of memory, in which case, multiple pages are allocated. However, since virtual memory is managed on a page-by-page basis, such units of storage may now exist partly in real memory and partly in a file on disk, thereby significantly easing the constraints on memory overcommittent.
OS/2 1.3 moved complete segments between main memory and the swap file. The fact that segments were variable in length complicated the management of both main memory and space in the swap file. There was also the requirement to regular memory compaction to reclaim the gaps, which formed when memory was freed. Under OS/2 2.0, in most cases there is no requirement to find contiguous pages in memory to satisfy an allocation request. Consequently, there is no need to move pages around in memory. The exception to this is the need for buffers used in DMA I/O transfer, which must be in contigous locations in memory.
Flat Memory Model
The memory model used by OS/2 2.0 is known as the flat memory model. This term refers to the fact that memory is regarded as a single large linear address space of 4GB, using 32 bits for direct memory addressing. This view applies for each and every process. Memory addresses are defined using a 32-bit addressing scheme, which results in a linear address space of 4GB in size.
Like the 80286 processor, the 80386 also supports a segmented memory model, except that in the case of the 80386 the maximum segment size is 4GB. While the 80386 processor does not explicitly provide a facility for disabling the segmented memory model, OS/2 2.0 implements the flat memory model by mapping the 4GB address space as a single code segment and a single data segment, each of which has a base address of zero and a size of 4GB. Only two segment selectors are therfore required in the system; an executable/readable code segment in the CS register, and a read/write data segment in the DS, ES, and SS registers. These selectors are known as aliases, since they all map to the same linear address range.
The 32-bit addressing scheme used by OS/2 2.0 is referred to as 0;32, or "Motorola mode", in order to differentiate it from the 16-bit segmented addressing scheme used by pevious versions of OS/2, which will be referred to as 16;16. These terms reflect the fact that the older segmented memory model uses a 16-bit segment selector and a 16-bit offset to refer to a specific memory location, whereas the newer flat memory model has no need of a segment selector, and simply uses a 32-bit offset within the system's linear address space.
The system's global address space is the entire 4GB linear address space. Each process has its own process address space, completely distinct from that of all other processes in the system. All threads within a process share the same process address space. This address space is also theoretically 4GB in size. However, the maximum size for process address spaces is defined at system initialization time and is somewhat less than 4GB, to allow space for memory used by the operating system.
Shown below is the mapping of a process address space into the system's global address space. The NN shown represents the maximum defined linear address space of the process address space, set at initialization time. OS/2 2.0 sets this limit to 512MB, reserving the linear address range above this point for operating system use. The space above 512MB is known as the system region
Note: The 32-bit region within the process address space is not used by OS/2 2.0, since "NN" is set to 512MB.
This limitation on the size of the process address space si used by the operating system to ensure protection of the system region from access by applications.
Conceptually, the process address space is divided up into two different regions, as shown above. One of these regions may be accessed by both 16;16 and 0;32 applications, known as the 16/32-bit region or compatibility region. The other region is accessible by 0;32 applications only, and is known as the 32-bit region.
The 16;16 addressing scheme allows access of up to 512MB per process, since the local descriptor tables used in this model contain up to 8192 entries, each of which can point to a segment of up to 64KB in size. In order to ensure that there is no problem in coexisting 16-bit and 32-bit applications under OS/2 2.0, the maximum size of the process address space has been set at 512MB. This means that all memory in the process address space can be addressed using either the 16;16. or 0;32 addressing scheme. This capability is important since it allows applications to be composed of mixed 16-bit and 32-bit code, allows 32-bit applications to make function calls to 16-bit service layers, and permits 16-bit applications written for OS/2 1.X to run unmodified, effectively allowing a "hybrid" memory management environment.
The 32-bit flat memory model greatly simplifies the migration of 32-bit applications to OS/2 2.0 from other operating system platforms, and the migration of OS/2 2.0 applications to other platforms. This is in contrast to the segmented memory model implemented by the 80286 processor. All the features described above arise from the fact that a flat linear memory model is used, taking advantage of the advanced features of the 80386 processor. The paging scheme is more general than the segmentation scheme used by the 80286, and the flat memory model will facilitate any future migration other than the Intel 80x86 family.