Page 343 - DCAP103_Principle of operating system
P. 343
Principles of Operating Systems
Notes Each object header also contains a quota charge field, which is the charge levied against a process
for opening the object. If a file object costs 1 point and a process belongs to a job that has 10
file points worth of quota, the processes in that job can only open 10 files in total. In this way
resource limits can be enforced for each object type separately.
Objects occupy valuable real estate—pieces of kernel virtual address space, so when an object
is no longer needed it should be removed and its address space reclaimed. The mechanism
for reclamation is to have a reference counter in each object’s header. It counts the number of
open handles held by processes. This counter is incremented every time the object is opened
and decremented every time it is closed. When it hits 0, no more users hold handles to the
object. When an object is acquired or released by an executive component, a second counter is
incremented or decremented, even though no actual handle is issued. When both counters hit 0, no
user process is using the object and no executive process is using the object, so the object can
be removed and its memory freed.
The object manager needs to maintain dynamic data structures (its objects), but it is not the only
part of the executive with this need. Other pieces also need to allocate and release chunks of
kernel memory dynamically. To meet these needs, the executive maintains two page pools in
kernel address space—for objects and for other dynamic data structures. Such pools operate as
heaps, similar to the C language calls malloc and free for managing dynamic data. One pool is
paged and the other is nonpaged (pinned in memory). Objects that are needed often are kept
in the nonpaged pool; objects that are rarely accessed, such as registry keys and some security
information, are kept in the paged pool. When memory is tight, the latter can be paged out and
faulted back on demand. In fact, substantial portions of the operating system code and data
structures are also pageable, to reduce memory consumption. Objects that may be needed when
the system is running critical code (and when paging is not permitted) must go in the nonpaged
pool. When a small amount of storage is needed, a page can be taken from either pool and then
broken up into units as small as 8 bytes.
Objects are typed, which means each one has certain properties common to all objects of its
type. The type is indicated by a pointer in the header to a type object, as shown in Figure 11.3.
The type object information includes items such as the type name, whether a thread can wait
on the object (yes for mutexes, no for open files), and whether new objects of this type go on
the paged or nonpaged pool. Each object points to its type object.
The last thing a type object has is also the most important: pointers to the code for certain standard
operations such as open, close, and delete. Whenever one of these operations is invoked on an
object, the pointer to the type object is followed and the relevant code located and executed.
This mechanism gives the system the opportunity to initialize new objects, and recover storage
when they are deleted.
Executive components can create new types dynamically. There is no definite list of object types,
but some of the more common ones are listed in Figure 11.4. Let us briefly go over the object
types in Figure 11.4. Process and thread are obvious. There is one object for every process and
every thread, which holds the main properties needed to manage the process or thread. The
next three objects, semaphore, mutex, and event, all deal with interprocess synchronization.
Semaphores and mutexes work as expected, but with various extra bells and whistles (e.g.,
maximum values and timeouts). Events can be in one of two states: signaled or nonsignaled.
If a thread waits on an event that is in signaled state, the thread is released immediately. If the
event is in nonsignaled state, it blocks until some other thread signals the event, which releases
all blocked threads. An event can also be set up, so after a signal has been successfully waited
for, it automatically reverts back to nonsignaled state, rather than staying in signaled state.
336 LOVELY PROFESSIONAL UNIVERSITY