• No results found

Components for Operating System Design

N/A
N/A
Protected

Academic year: 2021

Share "Components for Operating System Design"

Copied!
6
0
0

Loading.... (view fulltext now)

Full text

(1)

Components for Operating System Design

Alan Messer and Tim Wilkinson SARC, City University, London, UK.

Abstract

Components are becoming used increasingly in the construction of complex application software. Operating systems suffer from similar complexities, causing a move to micro-kernel architectures.

In this paper, we propose low-overhead technique for providing components that allow the level of coupling between components to be varied at run-time. In doing so, we indicate their use in a component-orientated operating system to allow its components to be ‘hot-plugged’

during execution.

Introduction

Complex software suffers from problems of maintainability and portability. To limit these problems, many software methodologies, such as modules and object-orientation have been created.

With the increasing complexity of a modern operating system, such methodologies have been adopted by operating systems designers.

The most recent example is the move to micro-kernel architectures, where services are moved from the kernel into user-space in order to separate each system’s complexity.

Such micro-kernel systems differ in the level of coupling they provide between the kernel and services. Some [1] rely on object- orientation to reduce coupling, whilst others [2] rely on operating system support (ports).

Language support with protection domains has the advantage of allowing kernel-service access with low-overhead, whilst operating system support means that the interfaces are more clearly defined at the cost of speed.

The latest methodology to hit the software business is components: objects with clearly designed interfaces that can be interconnected to form software in building block fashion.

Component objects are really an extension of the object-oriented paradigm where the calling interface is well defined and all calling is indirect through this interface. In doing so, they reduce the coupling between components allowing them to be changed.

Several such systems exist with a variety of aims. Unfortunately, these existing systems [3, 4, 5] provide too high overhead to be used for more than the larger granularity software components of an operating system.

The most popular CORBA [3] provides such facilities in a heterogeneous environment between applications. In the distributed system field systems such as: Regis [4] and the Polylith [5] provide a lower overhead solution for building composite applications. It is this latter work, which bears the closest similarity to the components proposed in this paper.

In this paper, we propose techniques for providing components that allow the level of coupling between components to be varied at run-time. In doing so, operating systems can be constructed from components and tightly interconnected where performance is a concern. As a side-effect the nature of the dynamic modification of any part of the operating system lends itself directly to 24x7 computing and mobile computing.

Existing operating system techniques

Reduced coupling between modules exists already at a higher level in operating systems, especially micro-kernels.

Dynamically linked libraries are the simplest form. A program can at creation or run-time

(2)

link itself to a dynamic library and call into it.

The interface is defined by the external references from the program and library. If at compile and run-time the interfaces match, the components are dynamically linked. This represents a close form of linking between the two participants and thus involves little overhead.

Other systems, such as Mach, support a looser coupling between participants through the use of ports. Each port provides a message queue to the destination (a mailbox) with N-to-1 semantics. This provides buffering between client and server, allowing both source and destination to be changed at run-time. The overhead of such a call is much higher than before. Rather than just a procedure call, a message must be: formed, sent to the port via the operating system, queued and collected by the destination. However, the interface between objects is made explicit and provides more flexibility.

At the far extreme are systems based on Linda tuplespaces [6]. Rather than supporting indirect messaging or procedure calls, all communication is performed using tuples (a variable record) which are placed in the tuplespace as offers or requests and matched together by the tuplespace. By doing away with knowledge of the destination or existence of a client or server or their interface, any component can be easily changed, but overhead is severely affected in the matching of tuples.

Several systems support a combination of methods of linking code. For example, most operating systems support static and dynamic libraries and kernel loadable modules. These, however only represent the more direct subset of possible linking techniques required.

Each type of calling convention has its place, dependent on its use. For example, it would be horrendous to use a tuplespace between a DSM server and the real memory system.

Likewise, direct procedure calls are not suitable for linking ‘hot-plugged’ device drivers in 24x7 computing.

We propose using a uniform component framework, where components can be constructed without knowledge of their interconnection. This interconnection can then be chosen to suit the functionality and performance required. An operating system constructed from such a system can then be potentially dynamically changed to suit the situation, as with 24x7 and mobile computing.

Functionality of the framework

In order for components to be written in such a way that they do not know how they are interconnected, the communication mechanism must be transparent to the component. It is impractical to introduce a new language or stipulate the use of an existing one to permit this, since most code is already written in established languages. This leaves us with a choice of altering one of the existing mechanisms used, either: message passing or procedure calls. Of the two, procedure calls are the best candidate, since they are the most common and provide the least existing overhead.

Since an existing procedure call provides a fixed destination, we must adopt the same approach used by dynamic linking, that of indirect procedure calls. Whenever a component call is required, an indirect call through the component’s Component Link Table (CLT) is performed (see figure 1).

Once inter-component procedure calls become indirect, the run-time support for the framework (pico-kernel) has dynamic control Destination component

Component Link Table Code

Source component

Code

Figure 1: Indirect component call

(3)

over the calling system used between components, allowing a variety of calling systems. For example, an extra component can at run-time be inserted in the call to provide an inter-protection domain call, should protection currently exist between objects (see figure 2).

Likewise, a queued mailbox, similar to a Mach port can be constructed, by placing a small component at the destination that actively delivers procedure calls to the destination in turn (see figure 3).

Tuplespace calling can even be achieved by providing stub components are each end. At the source, a procedure call to tuple conversion component is used to convert the procedure call interface into a typed tuple. This tuple contains the procedure required (service), its arguments and an enquiry for the result. At the destination, an active component places service availability tuples into the tuplespace indicating the procedure available and enquiries for arguments. These stub components can both then use a shared tuplespace component to perform the matching (see figure 4).

In each case, the appearance to the component is that the source performs a simple procedure call, whilst the simply destination receives them. This leaves the type of interconnection to be chosen by the pico-kernel, the component or a third-party dependent on speed or functionality.

An advantage of this alterable interconnection strategy is that the basic component indirection incurs little overhead, whilst any additional functionality and thus overhead may be used if required. We stipulate that this will allow complex performance sensitive software such as the rest of the operating system to be built out of such a framework.

Dynamic modifications

Another advantage of the framework is that the components can be changed dynamically. This is especially important in operating systems for 24x7 and mobile computing. Where due to external influences, systems components (such as devices) may appear, disappear or need substituting.

In order to achieve this functionality it is important that the pico-kernel can modify a component’s CLT atomically. Since we wish to minimise the overhead of the interconnection, using locks to obtain mutual exclusion on the table is not suitable. Instead the pico-kernel must provide system calls to achieve this, by blocking interrupts.1

With this functionality, access to devices likely to fail or disappear can be called through a queued or transaction based component. If however, a component is expected not to change in the short term (a PCMCIA hard disk) it can be called through faster mechanisms and be informed before the device is removed.

1 Instead, in the distributed case, it must protect the pages containing the table, preventing access until the interconnection has been modified.

Source Destination

Figure 4: Tuplespace calling Tuplespace

Source Destination

Protection domain switch

Figure 2: Protection domain component switch

Source Destination

Call queue and active dispatch

Figure 3: Destination queuing

(4)

Providing the interface

Each component in the system has a well- defined interface that is used to determine which procedures the framework will export and which procedure calls are inter- component.

In this paper, we assume that some form of component definition is available for the compiler or pre-processor to have access.

Typically, since most languages do not provide this information, this interface definition is separate to the source code itself. This is the Interface Definition Language (IDL) for which much work already exists [3, 4].

With this interface definition, either a pre- processor or the compiler for the language used can turn calls to another component’s procedures into an indirection through the component’s CLT. This component link table can then be accessed via a well-known name in the object’s symbol table.

In languages such as C++, it is even possible to integrate the component definition into the language and extract the component interfaces directly from the symbol table. This is similar to the Late Binding in C++ found in [7].

Using this technique, components can be expressed as a special class from which public methods of any sub-class are the component’s interface. A simple modification of compiler causes the compiler to emit calls to these objects as indirections through the component’s CLT.

The resultant object file contains the link table (the external calls) and by scanning for derived methods of the special component class, the exportable procedure interface to the object as a component can be obtained.

Component summary

To summarise, we shall discuss the various issues together in a particular situation.

Consider components written in C++ using a slightly modified compiler. All public method calls to an object derived from a special class called Component are inter-component

calls. A CLT entry in the object for the class (and thus component) is built by the compiler and indirected through. The constructor for the Component provides its interface to a well- known interface service component to which a default interconnection is made. This interface is extracted by the compiler as all the public methods derived from the Component object.

With late binding as in [7] this interface can be extracted at run-time for type-checking.

The CLT is stored in the component’s data segment and is modified by the pico-kernel (through higher-level calls) when interconnections need to be modified. By storing the link table in the component’s address-space, no operating system intervention or access is required once the interconnects are unchanged. This leaves the performance of the basic inter-component call is only slightly affected, with the single extra indirection.

When the component is created it has its interconnections set-up by itself, the operating system or a third-party and during its run-time they may be changed through the pico-kernel.

Operating system from components

To construct an operating system out of such components, a small kernel (the pico-kernel) must be provided to provide the framework itself. The pico-kernel provides nothing but system calls to change component link tables.

Above the pico-kernel is whatever operating system is being constructed. This will usually include higher-level management of the components, using operating system abstractions.

In figure 5, we see an example component operating system structure based around that of a micro-kernel. The pico-kernel at the lowest level above the physical devices provides system calls for maintaining the interconnections only. No abstraction of the CPU, memory or of a process is provided.

(5)

Above this are virtual device components for multiplexing and arbitrating access to physical devices. This allows multiple abstractions to be presented by higher-level components. This can be seen by both a native and hosted CPU being multiplexed on the actual CPU. Above these, higher level components exist providing abstractions which applications can use.

In such an operating system, the use of components throughout the system allows the ability to change any of the inter-connections.

As an example, if trusted, the DSM server can be placed in the same protection domain as the rest of the traditional micro-kernel (CPU and Memory), reducing overhead. Also, a virtual device (perhaps network) component servicing an application may be replaced by a queue when the device disappears.

The pico-kernel only provides management of the component interconnections. Thus, it is the operating system components’

responsibility to provide higher-level access to the components.

In a typical component operating system this will include: interface name services, component-level access and support for components from the operating systems abstractions.

The interface name service is a well-known component that knows the interface of components when created and allows components to find each other. Component- level access allows components to alter their

interconnection configuration and become aware of the types currently in use.

Discussion

It is important that the functionality of the pico-kernel is minimised when components are used so low in the operating system, since little control is provided over the CPU and memory subsystems. This means the component mechanism, both run-time support and data-structures must be also minimised.

For this reason, the pico-kernel only provides calls for maintaining the CLT. Any other functionality that needs to pertain to operating system abstractions of processes, objects, etc.

must be provided by the operating system being built.

Given the potential for dynamic modification of parts of the kernel, it is likely new components would be interconnected which where not known at compile-time. In these situations link-time or run-time type-checking is required. Link-time type checking is already found in dynamic linking and many languages contain support for run-time type checking of the procedure interfaces.

State is an obvious concern when interchanging components, for which a component framework cannot compensate.

Instead new objects must either be able to acquire the new state or start from a safe state.

Alternatively, before replacement, a functioning component may have interconnections to it monitored by inserting transaction based calling or have their state checkpointed.

Conclusions

In this paper, we have presented a uniform component framework that allows the level of coupling between components to be varied at run-time.

This ability to vary the coupling is achieved by allowing the calling convention to be changed dynamically by a modification to normal procedure calls. In doing so, basic component

Memory CPU Other

Virtual CPU Virtual Other Virtual Mem

Host CPU

Abstract Mem Native CPU

DSM Server Host App.

Local server

Application

Figure 5: An example component operating system

Pico-kernel

(6)

interconnection should be achievable with low-overhead.

Support for a range of possible calling conventions are discussed, which allow extra functionality to be used where and when necessary.

Finally, the structure of a micro-kernel operating constructed from such components is briefly discussed along with its potential uses.

Bibliography

1 K. Murray, A. Saulsbury, T.Stiemerling, T.

Wilkinson, P. Kelly, and P. Osmon.

“Design and implementation of an object- orientated 64-bit single address space micro-kernel,” in 2nd USENIX Symposium on Microkernels and Kernel Architectures, Sept. 1993

2 R. Rashid, R. Baran, A. Forin, D. Golub, M. Jones, D. Julin, D. Orr, and R. Sanzi.

“Mach: A Foundation for Open Systems.”

In Proceedings of the Second IEEE Workshop on Workstation Operating Systems, Sept. 1989.

3 “The Common Object Request Broker:

Architecture and Specification.” Object Management Group. Document Number 91.12.1

4 J. Magee, J. Kramer, and M. Sloman.

“REGIS: A Constructive Development Environment for Distributed Programs.”

Distributed Systems Engineering. 1(5):663- 675, 1994.

5 J. M. Purtilo. “The Polylith software bus.”

ACM Transactions on Programming Languages and Systems. 16(1):151-174, 1994

6 N. Carriero and D. Gelernter. “How to write parallel programs: a first course.” MIT Press, 1990.

7 T. Wilkinson. “An Implementation of Late Binding Functions in C++.” Technical Report, City University. 1995.

References

Related documents

A number of samples were collected for analysis from Thorn Rock sites in 2007, 2011 and 2015 and identified as unknown Phorbas species, and it initially appeared that there were

Reporting. 1990 The Ecosystem Approach in Anthropology: From Concept to Practice. Ann Arbor: University of Michigan Press. 1984a The Ecosystem Concept in

This study investigates how the competition factor affects the continue play intention in mobile games, with considering perceived enjoyment, switching cost, perceived justice

As a niche specialist recruitment consultancy cer Financial recruit within the following disciplines: Operations l Cash Management l Client Services l Commodity Trade Support l

As Justice Ginsburg pointed out, upholding the Top Ten Percent Law means turning a blind eye to the constitutional principles and goals of the Court's housing

Simplified CDD measures are not acceptable whenever a customer has been identified by the Banking Commission as non-complying with the FATF 40 and FATF Special 9, or for which

The Lithuanian authorities are invited to consider acceding to the Optional Protocol to the United Nations Convention against Torture (paragraph 8). XII-630 of 3