Computer and OS Structure


Device speed

What do we mean "I/O devices are slower than CPU" ?




Interrupts

Modern OS driven by interrupts.

Originally - Keep CPU busy, so have asynchronous I/O, don't have CPU waiting.

Now - Keep CPU free (responsive to user) so, also, asynchronous I/O, no CPU waiting.

Interrupts are to do with the massive asymmetry between CPU speeds and device speeds. They are how the OS "program" runs on hardware with very slow devices. Instead of the hardware just running the OS stream of instructions, it runs it in fits and starts:

repeat at random intervals:

 hardware interrupt
 OS save state
 run OS interrupt handler
so OS can run at different speed to the hardware devices.




Examples of Interrupts




Interrupts sidebar - Infinite loops

Question - Does infinite loop cause interrupt?

- The Halting Problem (Turing, 1936).

Might just be a long loop. We have no way of knowing. But still, even if long loop, control must switch occasionally - time-slicing. It is a timer interrupt that switches control. Loop runs forever, time-sliced.

- Fermat's Last Theorem. If could detect infinite loop, then could solve all problems of the form:

Does there exist a solution to f(n)
for n > t?
by asking the OS if the following:
repeat
 n := n+1
 test solution
until solution
is an infinite loop, or just a long loop? Then our OS could solve many of the world's great mathematical problems, such as Fermat's Last Theorem. Many other mathematical problems can be phrased as infinite-loop problems.




Note that many "infinite loops" actually terminate with a crash, because they are using up some resource each time round the loop. e.g. This program:

f ( int x )
{
 f(x);
}

f(1);
will eventually crash with a stack overflow.
This program however:
while true { }
will run forever, time-sliced.




Interrupts - Keeping the OS in charge

Interrupt idea is a way of periodically keeping the OS in charge so nothing runs forever without reference to the OS. e.g. In time-slicing, periodic timer interrupt to give OS a chance to do something else with the CPU.

Remember, the CPU is just looking for a stream of instructions to process, whether they come from the "OS" or from "user programs" it doesn't much matter to it. When the OS "runs" a program, it points the CPU towards a stream of instructions in the user program and basically hands over control. How do we know program cannot now control CPU for ever?

Note: Interrupt does not necessarily mean that OS immediately attends to the process that sent it (in the sense of giving it CPU time). It just means the OS is now aware that that process wants attention. The OS will note that its "state" has changed.

Single-step mode - Trap after every instruction.




Dual mode

"Keeping the OS in charge" means that there is a concept of an "OS-type program" (which can do anything, including scheduling ordinary programs) and an "ordinary program" (which is restricted in what it can do on the machine).

The restrictions on the "ordinary program" are normally not a problem - they are basically just: "Other programs have to be able to run at the same time as you".

This obviously makes sense in a multi-user system, but in fact it makes sense on a PC as well. When you're writing a program and you make an error, you don't want your crashed program to be able to crash the whole OS. You still want to be able to turn to the OS (which should still be responsive) and say "terminate that program".

Also user might run malicious prog by mistake (virus, client-side program on Internet).

Mode bit added to hardware to indicate current mode: user mode or system/monitor mode.

boot in system mode, load OS
when run program, switch to user mode

when interrupt, switch to system mode 
 and jump to OS code

when resume, switch back to user mode
 and return to next instruction in user code
Privileged instructions can only be executed in system mode.
e.g. Perhaps any I/O at all - user can't do I/O, user has to ask OS to do I/O for it (OS will co-ordinate it with the I/O of other processes).




Kernel

Consider from low-level to high-level:

  1. Parts of OS that are not scheduled themselves. Are always in memory. Operate in system mode. This part of the OS is called the kernel.
    Includes:

    
    
  2. Parts of OS that can be scheduled. Come in and out of memory. Operate in user mode.
    Includes:

    Parts of OS that could be in either of the above:

    
    
  3. Applications. All scheduled. Come in and out of memory. Operate in user mode.




Dual mode - Security

Need hardware support:




Memory protection

Basic idea is that there is such a thing as a "bad" memory access. User process runs in a different memory space to OS process.

On multi-process system (whether single-user or multi-user) each process has its own memory space in which (read-only) code and (read-write) data live. i.e. Each process has defined limits to its memory space:

Even if no malicious people, process memory areas need to be protected from each other - Why?

Above, each process has 2 registers - a base register and a limit register.
e.g. The base register for process 2 has contents 5200000. Its limit register has contents 3200000.
And then every memory reference is checked against these limits:


When reference is made to memory location x:

if x > base
{
 if x < (base+limit)
  then return pointer to memory location
 else
  OS error interrupt
}
else
 OS error interrupt


This check is not in software but is hard-coded in hardware. (Why?)

This check not done in system mode - unrestricted access. Why?
Load values into base or limit registers are privileged instructions. Why?

As we shall see later, memory protection has evolved quite far beyond this simple model.




Command Interpreter

Two approaches:

You can customise your DOS command-line to make it more like UNIX. Can even buy UNIX shells for it (and other DOS shells, and many different shells on UNIX itself).



Virtual Machine (VM)


Virtual machine



Java Virtual Machines

The idea of implementing a virtual piece of "hardware" has returned with the idea of a Java Virtual Machine. Java is a language designed for a machine that does not exist, but that can be simulated on top of almost any machine. Promises:

  1. Portability. Write an application once, run everywhere.
  2. Run remote Internet programs on client-side. Idea is that you can run programs of a remote machine (website), but you run them on your machine. i.e. Client-side processing as opposed to server-side processing (CGI).

Java is a HLL. It is "compiled" to "virtual assembly" (instructions/operands, bytecodes that can be transmitted over network), these run on Java VM, where they are actually mapped to native code. Java VM exists everywhere. In fact, the Compiler also exists everywhere, so Java can actually be used as interpreted language - the Java HLL can be transmitted over the network. Common client-side programs:

The Java / client-side idea is good in theory but in practice we have seen these promises betrayed by the market and by human attitudes:

  1. No portability in practice. - Java, Javascript programs that one meets online have often only been tested on IE on Windows, and may not work (or may even crash your browser) if you are using any other browser or OS.
  2. The whole idea of client-side programs becomes a way for engineers to show off to their peers, while annoying you and wasting your time and crashing your browser.



The failed promise of Java

Summary: I'm not complaining about Java itself as a programming language. I'm complaining about client-side network programs.

And I'm only against client-side programs because the OS market is a monopoly. So client-side programs are vicious enforcers of that monopoly. "Vicious" because they crash your browser or even your machine if you do not obey the monopoly.

If sometime in the future the OS market becomes competitive, then client-side programs might become cross-platform, and my view of them might be different.


I've finally figured out why I don't like Java. You would think that a UNIX person like myself would love Java. After all, it promises that people will write applications for Windows, and they will run on UNIX. It was even meant to be the last great hope to save us from a Windows future.

But instead Java has become the most aggressive platform-enforcer of my lifetime.

The idea of Java was that it would be a language whose programs would run unchanged anywhere (not even just recompiled as in C/C++). Of course, humans being what they are, many people are hard at work trying to thwart this promise. Java (or Javascript) on a web page now often mean that you have to use Microsoft Windows. Authors use Windows-specific tricks, and have found the most aggressive means yet of punishing you if you don't use Windows. Many mainstream web sites use code that will crash your browser if you dare to use UNIX.

There are many other Windows-dependent technologies offline, of course, but you never have to see them. They don't bother you. But Java (and Javascript)'s Windows-enforcement is in your face all day long.

It is not as if there is a platform-independent alternative (at least without re-compiling) so it is a shame that Java has ended up as an obnoxious Windows-enforcer. Its promises to be platform independent ring hollow compared with CGI, which really is platform independent, and works on every machine under the sun. CGI is what Java failed to be.



So what is the cross-platform future? XML plus server-side processing will work on everything. As for client-side processing, I don't know.

In fact, it may be that any client-side processing system will inevitably end up as an obnoxious Windows-enforcer, so we should just stick to server-side processing.




Write OS in Assembly or HLL?

HLL more portable, and easier to write/debug/change:

"Assembly is faster" - But nothing is as fast as a good algorithm. Improved algorithms and OS data structures have historically been far more important than what language written in. (This is true for other large systems).

Also, an expert Assembly programmer may produce faster code by hand, but will you really? The knowledge of many Assembly experts is built-in to your compiler. Running the compiler on your HLL code with the -optimise switch may well generate faster Assembly code than anything you could have written yourself.