CM10195 Computer Systems Architecture 2 Revision Notes
CM10195 Systems Architecture 2
Introduction to Operating Systems
An operating system is often called the kernel it is a bridge between hardware (cpu, memory &
devices) and software applications. The OS will manage the computer’s resources (i.e the
hardware & software) to make sure (as they have limited usage) they are shared usefully, as
well as giving the programmer a usable interface to access them. Relating to the Von Neumann
architecture, the programmer does not want to have to know a machines hardware specifics
when writing a program they use a common OS which then interacts with the hardware so it
can be used on any machine with that operating system. This also provides a common standard
interface, making programming applications easier, and the operating system can make full use
of the hardware than if a coder were to handle this individually.
Warning; The end user GUI that we see onscreen is not part of the operating system it is just a
program that uses the OS! When GUI’s were tied to the OS, a bug in a program running would
cause the whole os to crash wiping out the machine entirely, and allowed an easy breach of
security as this method circumvents the protection the OS provides.
As modern computers are fairly compact (mobile phones, netbooks, even laptops), they have
minimal resources and so there are strict limitations on usage such as memory and cpu, as
well as energy consumption for those machines running on battery power. The OS will manage
these resources to limit their usage.
These resources are also protected by the operating system, in situations such as security one
program corrupting another, authorisation ensuring only the resources allowed for a program
are used, authentication ensuring the program is authorised to use the resources it claims to
need, and protection from your own mistakes.
Resources also need to meet certain criteria, such as responsiveness processing
computations as quickly as possible, real time generate an (almost) immediate response to an
input, and security preventing unauthorised access/modification to them.
The layers of a computer;
The OS should be lightweight and efficient as to not detract from the cpu usage needed by the
programs that are being run by the user. It should also be flexible as to not get in the way of the
As operating systems are almost as old as computers, people tend to get confused between
them. As an OS is just a program, an OS can run on any hardware, and vice versa a piece of
hardware can run any OS. Current Mac hardware is the same as PC hardware, so you can run
Windows, MacOS, Linux and many other OS’s.
Well designed operating systems are hardwareindependent apart from the elements that need
to actually physically access the hardware. This makes them fairly portable from one
architecture to another. This historically did not happen, as OS’s were tied to hardware so
intricately that portability was difficult.
Phone operating systems are marketed for their GUI rather than their operating system, and
phone vendors tend to make it hard for users to access the actual operating systems on the
phones themselves. Operating system owners in general (Microsoft, Apple) tend to market their
operating systems as their GUI’s, but they are not the same.
The term PC refers to Personal Computer, and refers to the hardware, rather than the operating
system being run on it Macs are PC’s too.
An operating system should be chosen with several factors in mind; Ease of use, efficiency,
security, stability, suitability for tasks, etc. There are many operating systems in existence, and
embedded operating systems far outnumber PC operating systems.
Historically, computers did not have operating systems, as each programmer would write
programs for the individual computer they were using so there was not portability. This also
meant there was a lot of repeated code between programs programs were created on a punch
card along with the data (program and data collectively called a job), which were then given to an
operator with scheduling turnaround possibly days, and the programmer could only then fix any
Useful programs were created common functions and tools to minimise repeated code,
making program management a lot easier. However the large computer was always needed to
be kept busy, as when it was idle it was wasting time and money. To counteract this, operators
put the programs on to a fast medium (magnetic tape) and the computer loaded and ran them
as fast as possible. This is the first instance of spooling, a queue (or buffer) of jobs to be done,
and was the first addressal of the difference between human and computer speeds. Spooling
was also used on output for printing.
Spooling would later become automated a monitor will load and run programs and store results
somewhere suitable. This would be directed by a job control language. The IBM job control
language was called JCL allowed different classes of job, scheduling of jobs and automatic
charging for use of the machine from these jobs. It also allowed batch processing several
programs to be collected and loaded at the same time for efficiency reducing loading and
When the monitor loaded more than one program at once, if program 1 was writing to tape, then
program 2 could use the CPU in the meantime. However if something goes wrong with one
program, not only would the monitor become corrupted, so would the other program. Therefore
some kind of protection was needed, as well as means of stopping infinitely running programs
The monitor code loads the program, then just jumps to the program code so the machine now
runs the program. The flow of execution goes as follows; Monitor starts program, program 1
runs until tape is needed, monitor sets up tape, monitor decided to run another program... etc.
There is a single stream of control jumping between the monitor and several programs so the
monitor is not running when a program is running this is called multitasking, even though there
is only ever one thing running. Multitasking improves efficiency, as the monitor can run another
program when a program is waiting e.g. for a slow peripheral.
To decide which programs should be run when, the monitor uses scheduling. Which program
run when depends on many criteria; how long a program has been running, a programs priority,
whether a program is likely to need to use of the CPU soon or later, how much the owner has
paid, etc. Scheduling algorithms have evolved from just running each program from start to
finish, to a more sophisticated model that factors in the criteria. However the more time the
monitor spends deciding which program to run, the less time the programs can actually run, and
so there is a trade off between fast and fair scheduling.
The program should also be well written, as if it goes into an infinite loop the stream of control is
never passed back to the monitor and the whole computer is jammed. To stop runaway
programs, a hardware clock/timer is used to regularly send interrupts. When the interrupt is
taken, the flow of control returns to the monitor so it can decide what to do next which can
include resuming the program that was interrupted, kill the program, or switch to another
program. Setting a clock to regularly send interrupts is called preemptive scheduling, which
enables timesharing. Timesharing is the sharing of the CPU time with several different
programs, so it seems they are running simultaneously, all mediated by the monitor.
Interrupts allowed the user to interact with the computer directly by the use of terminals, only
running a program when a command from the terminal came in. This means that no CPU
resources are used until they are needed. Frequent interrupts mean other programs can get a
slice of CPU time more often, so more programs can appear to be running simultaneously, and
an interactive program can appear to be dedicated to the user whilst the CPU can run other
things. However, frequent interrupts also means the stream of control keeps going back to the
monitor so it can decide what to do with the interrupt, meaning it is using up CPU time the
programs could be using. This is therefore a tradeoff between frequent interrupts meaning good
interactive behaviour, and rare interrupts meaning good computing behaviour. Interactive
programs usually get high priority but small CPU time slices, and computeintensive programs
get low priority but long time slices.
Thrashing is when an operating system spends more time on deciding what to do than actually
doing useful work, and many early OS’s had a problem with thrashing. To protect the programs
and monitor from each other, hardware mechanisms were used, which had to be fast and
unobtrusive. For example, operations like accessing tape or a printer should only be used by the
monitor, and not be accessible by a program. To solve this, the CPU instructions were split into
two categories; unprivileged any program can access these (e.g addition, jumps), and
privileged only certain privileged programs such as the monitor can access these (e.g
peripheral access). The processor can then run in either privileged (kernel) mode for system
operations, or unprivileged (user) mode for normal computation. Some processor architectures
have more than two privilege levels also called privilege rings. Unprivileged programs that try to
execute a privileged operation causes an interrupt or a system trap and sets the processor
into privileged mode, and then returns the stream of control back to the monitor which then
decided what to do like disallowing the operation or killing the program.
How the modes work; system starts in kernel (privileged) mode, monitor decided which program
to schedule, uses a special jump & drop privilege instruction to run the program, the program
runs unprivileged, the program finishes or decided it needs a system resource, the program
executes a syscall instruction (calls the monitor) which enables privileged mode so the monitor
regains control, and then the monitor decides what to do next. If the program does not execute a
syscall, the program will be interrupted at some point anyway. The program can’t enter privileged
mode as every transition to privileged mode is tied by the hardware to a jump to the monitor.
However jumping between kernel and user mode is a timeconsuming operation due to
overheads, which is why we don’t want timer interrupts too often.
Forcing access to the hardware via the monitor increases security of other system resources
like files or network, as the OS can enforce policy on access and ensure fair distribution of
Memory protection stops a program from reading/writing the memory used by another program
or by the monitor/operating system. The memory management unit (MMU) is a piece of
hardware that stores a series of flags which say if the program currently running can read or
write (2 separate flags) a given area of memory. The setting of these flags (which are effectively
just one bit a 1 or a 0) is a privileged operation, and if an unprivileged program tries to read/write
to an area of memory it is not allowed to, it is the MMU which raises an interrupt, and the monitor
takes control. The area of memory that can be flagged is called a page 4096 bytes. There is
also an executable flag can the program running execute code from this memory address. This
table of flags is part of the programs state, and must be saved and restored when the program
stops and is rescheduled. As every read/write must be checked against the flags, the checking
process must be fast.
Some of the requirements of a monitor (operating system) are therefore; resource management
scheduling CPU time, disk, network, etc. , Protection memory, files, network data etc,
Efficiency time, size, energy.
A process is an executable object, it’s data, and the associated information the operating system
needs to run it. A process is a program in execution. A single program may have more than one
process, and is structured by process. The operating system has to keep a lot of information
about a process, for example where in memory it’s stored, how much time it is allocated/used,
it’s flags from the MMU, etc.
A process can be in several states, the five main states being:
New a newly created process
Running currently being executed on the CPU
Ready ready to run but another process is currently using the CPU
Blocked waiting for an event or resources to become available
Exit a process that has finished
The operating system has a list of these processes and their states, so the scheduling the
monitor has to do can be thought of just decided which of the processes to move from one state
Processes in Unix are arranged in tree, allowing a large bunch of processes to be controlled as
a group. Each group within a tree has a session leader, which if killed would kill all the processes
in the group.
The process states goes from new, to ready, which can cycle between running, block and ready,
before becoming in the exit state. Here is a finite state machine describing the states of a
Typical transition; monitor schedules a process on the ready list, process is dispatched, process
can relinquish/be interrupted and goes in to the ready state, or sleeps/is blocked and goes into
the blocked state, or is released into the access state. Early os’s relied on a running program
written to relinquish control every once in awhile called cooperative multitasking. The new and
exit states only happen once per process.
Some other information a process must collect are; user ID’s, a priority, statistics like CPU &
memory used, it’s state, and a list of resources used particularly the memory for the code and
it’s data. This collection of data is called the process control block PCB.
To pause and restart a process requires the saving and restoring of the process state, stored in
the PCB. PCB’s of the various processes are stored as a linked list to allow for flexibility in
numbering and ordering.
In the new state, we have to do several things before the process can move on to the ready
state; allocate & create PCB structure, find a free PID, determine & allocate necessary
resources, determine initial priority & then insert the PCB into the relevant list. Although a new
process can be spawned/forked from another process, it must ask the operating system to
actually create the process using a syscall with specifications of the new process, and the
original calling process will become the parent to this new process.
On switchon of the computer, the processor jumps to a location in the nonvolatile memory
where there is an ancestor process called init, with PID 1, which serves to create all other
processes this is bootstrapping. It is complicated as it has to detect and determine hardware to
initialize it, set up all the data structures the operating system needs and start service
processing running, all before looking at what the user wants.
Scheduling is still a very difficult problem for the operating system and still has not been solved
they have to do many things such as give each process a fair slice of CPU, interactive
processes react to humans in good time, give as much time possible to computeheavy
processes etc.. and all very quickly.
Scheduling is usually subdivided into three classes; short term use of the cpu, medium term
which processes to keep/load into memory, long term deciding which processes to load into
the scheduling system. So, longterm scheduler determines processes for mediumterm, which
determines processes for shortterm which determines the processes to be run.
In shortterm scheduling, we need to quantify which process to run, using CPU cycles used,
memory/disk/network used etc. as well as throughput (jobs finished in a given time), turnaround,
realtime, money paid etc.
Run until completion First In First Out, good for large amounts of computation & no
overheads from multitasking, poor interaction with other hardware and no interactivity.
not suitable for modern machines
Shortest job first no multi tasking, good throughput, long jobs suffer, difficult to
estimate time completion
Run until completion + cooperative multitasking nonpreemptive, weak
multitasking, poor utilisation of hardware, poor interactivity, easy for a process to
starve other processes
Preemptive Round Robin each process gets a fixed time slice, multitasking,
utilisation of software, no starvation, interactive process given same time as
computeheavy processes, not good for interactivity or realtime.
Round robin suited to systems with equal importance processes (e.g network
routers splitting network capacity). Time slices awarded in circular order, nonstarvatio
Shortest remaining time next process chosen by shortest remaining estimated
time, preemptive, hard to estimate, good for short jobs, starvation.
Least completed next process consumed the least CPU time goes next, all
processes make equal progress, interactive processes get good attention due to
small usage of CPU, starvation of long jobs
We can determine if a process is interactive by high I/O per compute, if low then the process is
computeheavy. Priorities can also change throughout processing, they can be; static
unchanging which is simple but resistant to change, dynamic changes in response to the load,
or purchased more money = higher priority.
Highest response ratio next variant of shortest remaining time, takes time process
has been waiting since it’s last time slice into account priority = time so far / CPU so
far. time slices repeated until priority drops below another process, avoids starvation,
new jobs get immediate attention, critical shorter jobs can be starved. Requires lots of
reevaluation of priorities, so lots of scheduling overhead.
Multilevel feedback queueing multiple FIFO queues with different priorities from
low to high, new process starts at the end of the highest queue, a process moves to
the end of the next queue level down when it’s finished it’s time slice, or the the end of
the same queue if it relinquishes voluntarily, or at the end of a higher queue if it blocks
for I/O. Processes in highest level priority queue executed first. New short processes
get priority over older computeheavy processes starvation
Traditional Unx scheduling based on a timer interrupting every 1/60th of a second,
wth priority computer from the CPU use of each process base priority + (cpu time
used/2). CPU time halved every second so only applies to recent useage, priorities
recomputed every second. Smallest priority was chosen next, with same priority
treated as round robin.
Fair share scheduling each user of the machine rather than each process gets a
fair share of CPU time.
When we want to schedule multiple resources (not just CPU) the process calls the kernel and is
marked as blocked until the requested resource has arrived sometimes the delay between
request and reply from process to kernel and back is infinite.
Say process one wants access to memory disk 1 to copy data to disk 2, and process two wants
access to memory disk 2 to copy data to disk 1. The os grants p1 exclusive access to disk 1 &
p2 exclusive access to d2. Then when either p1 or p2 asks the os for access to the other disk,
they are both blocked due to the other process having exclusive access. This is called deadlock,
& can happen on any kind of shared resource requiring exclusive access with more than 2
A formal definition of deadlock a set of processes D is deadlock if each process Pi in D is
blocked on some event ei and event ei can only be caused by some process in D. Deadlock is
only possible if there is; mutual exclusion one process can use a resource at one time,
holdandwait process holds a resource while waiting for other resources, no preemption
no resource can be forcibly removed from a process holding it. A deadlock is possible if there
are these three factors, but will only actually happen if there is a circular wait circular chain of
process waiting on each other to release a resource that is needed by the next in the circle.
Indefinite postponement happens when a process never manages to get all of the resources it
needs could happen of holdandwait were to be dropped to prevent deadlock.
We can either prevent deadlock by preventing one of the conditions, or detect and break
deadlock by destroying one of the conditions when a deadlock occurs. Prevention is further
refined as constraining resource allocation to prevent holdandwait.
We can prevent deadlock by;
Breaking mutual exclusion although hard to break, we can make sure resources
are not held on to for longer than needed.
Breaking holdandwait can require a process not to hold any resources if it ever
gets blocked on another resource. Could also require a process to request all
resources necessary before going ahead. This prevents the process doing useful
work while one resource is needed but the other is needed yet, and process may not
even know resources needed from the start.
Breaking no preemption possible only for resources whose state can be saved
and restored easily.
Breaking circular waits putting an ordering on resources, so a process that
requests R in the order can then only request a resource after R in the order. This is
inefficient and causes unnecessary holding of resources, and is not always possible
for resource to know what to request will have to drop resource later in order and
rerequest from earlier in the order.
Deadlock avoidance does not stop a specific condition but doesn’t do anything that could
potentially lead to deadlock, but this is difficult as with each request it has to be checked that it
couldn’t cause deadlock in the future, which can be hard to predict.
The banker’s algorithm makes two tests; feasibility see if a request is possible i.e. the total
allocated resource doesn’t exceed the actual resource, and safety see if a request cannot lead
to deadlock i.e. there is at least one sequence of resource allocations and releases by which all
processes can complete their computation. An unsafe request will not be granted by the OS, nor
an unfeasible request. Therefore there must exist at least on path to completion for all processes
for a request to be granted. However, there are several problems with this algorithm; there must
be a fixed number of resources to allocate, fixed number of processes, processes must know
their maximum needs in advance etc.
Deadlock detection is different again, allowing deadlock but relying on noticing & breaking them,
spotting when the circular wait happens. One method of this uses resource request and
allocation graphs (RRAG), by simply finding circuits in these graphs using graph reduction
remove all available resource request links then remove all links from allocated units of resource
to the process. If we can reduces a RRAG by all process links, there is no deadlock, else we
have isolated the graph to just the deadlocking processes.
Then we just have to break the deadlock by either; killing one or more of the processes, preempt
the blocking resources (better), add resources. Deadlock avoidance is rarely used as prevention
is easier and cheaper. The more general solution is virtualization, where the operating system
pretends each process has exclusive access to a resource e.g spooling; instead of writing to a
printer, the process writes to a tape which is then later written to the printer. This means there is
no possibility of deadlock.
Suppose a low priority process holds a resource that a higher priority process requests the
higher priority process is prevented from running by the lower priority one this is called priority
inversion. This can be prevented by; priority inheritance priority of H is temporarily loaned to L to
get it out of the way, priority ceilings the resource is given a priority and no process with higher
priority can lock the resource.
Process protection is enforced by forcing access via the kernel so one user cannot interfere with
another user’s processes. For this, each user has it’s own ID which the OS determines which
process can access which files, other processes and so on. A new process inherits the userID
of the parent process. A root/administrator/superuser is a normal user but allows access to all
users files and processes etc. and while is not the kernel, the interuser protections are not
enacted by the OS. The root can change the userID of it’s processes, giving away it’s privileges
but allowing a normal user to have a process. Root access can be broken down into capabilities,
i.e. all the way down to rights access to individual files. These capabilities (or permissions) are
like tokens which can be passed around or inherited by processes and so on, and allow finer
control of security at the expense of a more complex checking system.
Interprocess communication (IPC) is how processes communicate amongst themselves,
sending/receiving data from each other etc. This can be achieved in many ways, but must be
supported by the operating system, as the kernel by default stops processes interfering with
IPC can be done using;
Files using an existing resource, PA writes data it wants to send to PB to a file, and
PB reads it. They must agree on a filename, know when data has arrived, the file must
have protections from other processes, and files are slow. Not used for IPC in general,
but good for huge amounts of data.
Pipes connects two processes taking output from one and giving it an input to
another. Provides coordination and synchronisation (one process can’t use the pipe
whilst the other is using it) which affects scheduling of the two processes.
Implemented as a buffer held by the kernel so it can control the scheduling, usually
used when a process forks a child process to channel the data from parent to child.
Pipes are simple, efficient, easy to use, unidirectional, only between related processes
and so used a lot. Can cause deadlocks. Named pipes are shared between unrelated
processes, and sockets allow bidirectional IPC between processes that could be on
Shared memory memory shared between the processes, so one process could
write to memory for another process to read. Have to decide what memory to use, a
flag to a specific memory location to signify the data has finished being written, and
memory protection from other processes. Due to fast speeds, good for IPC and large
chunks of data
Signals a software equivalent of a hardware interrupt, raised by the kernel or a
process with the same userID via the kernel, and the receiving process stops and
executes a signal handler. Just a flag bit, which can then be either; ignored, accepted
and acted upon, suspended, or terminated. They are asynchronous can arrive at any
point during the program’s run. Each type of signal (e.g KILL, PIPE, INT etc.) has it’s
own signal handler, but the program can include handler functions for doing something
different. Signals are fast, efficient, used for small data transmissions, and are used a
Semaphores a variable that can only be accessed and altered by 2 operations
signal and wait. Allows mutual exclusion, where only one process is allowed access to
a resource at one time. Used to protect shared resources, but hard to implement.
Widely used, small & fast, used in OSs and user programs to protect critical
resources. Easy for semaphores to cause deadlock.
Application level highlevel mechanisms of IPC, focusing on passing objects
between components. The standard method of representing the objects called
Gates’ Law programs double in size every 18 months
Wirth’s Law software is decelerating faster than hardware is accelerating
The first thing to consider in memory management is how processes their code and data
should be laid out in physical memory. Allocation needs to happen at several points; initialisation
(static), running (dynamic), freeing during running, freeing at end, freeing & allocation within the
Implicit memory management language controls creation and deletion of objects
Explicit memory management programmer controls the creation and deletion of the objects
Partitioning is a static layout of physical memory, with areas allocated at boot time, and a
process is loaded into the smallest free partition it will fit into. Equal sized partitions are easy but
waste space, and can’t cope with larger processes, and can only deal with a certain amount of
Overlays are when only part of the process code is loaded into memory at once, with the rest of
the process code being able to load into memory if needed, overwriting the part of the process
they do not need at the moment in memory. This costs speed and execution, and only for good
In physical memory we must fit on process into one block of memory as we can’t spread it
across several blocks, as it’s too complicated.
Dynamic partitioning creates and allocates partitions only when needed, allowing a process to
determine how big the partition is. When a process ends it leaves an empty space in memory,
creating fragmentation, which is holes of different sizes in the memory, all separated from one
another, making it harder for larger processes to be loaded into memory. To solve this efficiently
is hard, but we can keep a free list of all free spaces, and we can coalesce physically adjacent
blocks. When we want some space we can search the freelist, using a big enough chunk and
returning the unused space back to the freelist.
There are strategies for choosing the blocks of memory from the freelist;
First Fit First available big enough chunk, faster than best fit, leaves larger more
useful fragments, but leaves smaller fragments near the start of the list, meaning we
search further and further down the list each time.
Best Fit Smallest available big enough chunk, slower than first fit as we check the
entire list, and results in fragments too small to be of any use.
Worst Fit Biggest available chunk to leave behind useful large chunks. Faster than
best fit due to larger and fewer blocks to search through.
Next Fit continue from where we last allocated. Fast, improves on first fit by
spreading small fragments throughout memory rather than at the start of the list.
If there are no memory spaces big enough we use a compaction of memory called garbage
collection. This stops all processes, moves them around in physical memory to close the gaps,
and then the processes can continue. This is an expensive operation to move all the blocks
around, and pausing realtime behaviour is not ideal, and so garbage collection is not widely
Even with garbage disposal, is we can’t find a suitable free space for a new process, we can
choose not to admit it, or kill processes which is not ideal unless the new process is important.
It is better to preempt memory take it away from one process and give it to another.
Swapping one or more processes are selected by the OS to have their data copied out to disk
to make space for a new process usually blocked or unscheduled processes. When these
processes want to be run again, their data needs to be copied back into memory first. This has a
trade off between speed (time spent copying to and from disk) and size (memory allocation).
Usually is not used due to time consuming nature.
Paging chopping memory into regular sized portions called pages (4096 bytes), and the
hardware is arranged so copying pages in and out of memory from disk is as efficient as
A physical address is a number of the bytes in the system from 0 to n, where a virtual address is
a perprocess fictional address. The operating system has a table per process containing the
virtual to physical mappings for each process. The tables only contain addresses for pages in
use to keep their size to a minimum. This mapping is done for every memory access by the
CPU so must be as fast and efficient as possible, and so is supported by hardware called the
translation lookaside buffer (TLB) in the MMU. The TLB has it’s own copy of a few of the
mappings of the current tables to translate very quickly between them. The page tables are
stored in normal memory as part of the process’ management information.
When presented with an address from the CPU, the TLB looks it up in it’s cache if it’s there the
memory access goes ahead with the physical memory there, if it’s not there then in a hardware
managed TLB it will look for the translation in the page table itself called a page walk and stores it
in the TLB, in a software managed TLB, the OS has to do the page walk. If the TLB is full with a
TLB miss, the OS has to decide which address to delete to make room for the new one, usually
a least recently used (LRU) strategy is used due to temporal locality.
There are many strategies to evict a page when physical memory is full random, FIFO, LRU,
LFU etc. TLB’s are good but have small capacity and rely on temporal locality to be effective.
When a new process is scheduled the TLB has to be flushed for the different mappings of the
So a page table is a list of pages a process has accessed with relevant virtualphysical mapping.
Every page has some permissions attached; read, write and execute. The TLB solves two big
problems of memory protection and sharing, as all memory accesses go through the TLB which
can prevent it being possible for one process to overwrite the memory of another.
Copy on write different processes can share data as long as they do not try to update it, at
which point a page fault occurs and the operating system takes over, and creates a copy of the
page and changes the page table and TLB for that process to point to a new copy, and the write
can then take place on a private unshared copy
Another problem in physical memory is that it runs a lot slower than processors, called memory
latency a delay between a request to memory and the values coming back. One way of
addressing this bottleneck is using registers, doing as much computation in them as possible,
only calling out when necessary. These registers are small amounts of memory running at CPU
rate, called a cache, and it sits between the CPU and main memory. If the CPU needs to read
from memory, if the location is in the cache the value is returned, if not it is retrieved from main
memory and also stored in the cache.
A cache line is a small block of bytes that get written/read as a whole, reducing the lookup
system. Writing to memory is done through the cache via two methods; writethrough cache
value written to cache, cache writes to main memory, or writeback cache main memory is
only written to when convenient/necessary. We can have multi level caches, and caching
happens at many levels in registers, in the TLB, in L1, L2 & L3 caches, main memory is a
cache for disk, etc.
Temporal locality recently accessed location will likely be accessed again soon
Special locality locations near recently accessed locations will likely be accessed soon.
Some architectures have two separate caches one for code and one for data, due to their
different behaviour data has lots of reads and writes, code has lots of reads. This architecture
is called the Harvard Architecture, with the idea for separating the two produces higher hit rates
for each cache individually.
Cache flush requires all cached values to be written to main memory and then clears the cache.
Cache coherence is when all the processors see the same values in memory. This is difficult
with multiprocessors, as each processor has it’s own cache. So each cache must watch every
other cache. The largest multiprocessor machines have either;
Nonuniform memory access some parts of memory are slower than others (as one part of
the memory is design for access by that processor (fast) but the rest is for the other processors
Nonshared (distributed) memory cluster of processors joined by a network.
Main memory these days is several gigabytes and is volatile, but to manipulate more data we
turn to larger but slower devices like disks, with organised filesystems. A file is a named chunk of
data stored on a disk, it’s name converts to places on disk using a hierarchy. We gather related
files and put them into a directory (or folder), and names of directories can be collected into a
directory and so on until we reach the root, or the top of the hierarchy. The directory hierarchy
forms a directed acyclic graph (DAG), meaning there are no loops for easy traversal of the
hierarchy. Each process has a current working directory (cwd), which is a prefix (stored in the
PCB) which is glued onto an incomplete filename and the kernel uses that instead.
We want to do a lot of things with a file system, including; creating, deleting, opening, reading
from, writing to, closing and renaming a file, and creating, deleting, looking through, adding,
removing and renaming files from a directory. This is before coming to things like, speed of
access/update, scalability, efficient disk space use, reliability, protection, security, backup &
The design of a Unix file system is based on inode (data structure), where each file has an inode
that contains information about a file it’s metadata, such as; timestamps, ownership, size, type,
access permissions, reference count etc. Filenames are not stored in the inode, but in the
directories, which are essentially just a list of names of files and subdirectories with their inode
numbers. There can be multiple directory entries of the same inode with a different name
hence why a file’s inode does not store it’s name. If the reference count (number of names it
has) of an inode is zero, then the operating system can remove the file. Deleting a file will
decrease the inode reference count and removing the name reference in the directory. Inodes
are in disk blocks, allowing for quick allocation/deallocation. A soft link (shortcut) is the name of
the file, whilst a hard link refers to the actual file.
When a program opens a ﬁle, the OS must ﬁnd where on disk the ﬁle lives, so say we are
looking for the ﬁle prog.c with a cwd of /home/rjb;
The name is incomplete, so the OS prepends the cwd giving /home/rjb/prog.c
The OS reads the block containing the root directory off disk and scans through it for the
● It ﬁnds it and gets the inode number for home
● It reads the inode off disk and ﬁnds it refers to a directory
● It reads the block containing the directory off disk
It scans the directory for the name rjb
It ﬁnds it and gets the inode number for rjb
It reads the inode off disk and ﬁnds it refers to a directory
It reads the block containing the directory off disk
It scans the directory for the name prog.c
It ﬁnds it and gets the inode number for prog.c
It reads the inode off disk and ﬁnds it refers to a ﬁle
It reads the blocks containing the ﬁle off disk
This must be done for every file opened. Caching can be used here to keep inodes and
directories in memory for quick access.
If we want more than one file system on one disk we can split the disk into partitions, which is
just a chunk of disk owned by a single filesystem. Each file system has it’s own inode tables
separate from the others. As inode 23 of one file system is different to inode 23 of another
system, we can’t have hard links across partitions, but we can have soft links.
A disk is a large array of block of either 514 or 1024 bytes, numbered from 0 up to the number of
blocks on the disk. This type of addressing, with a 48 bit address, is called linear block
addressing (LBA). A disk comprises of 3 or 4 platters covered on one or both faces with a
magnetic material which are spinning at great speed. Data is written and read from these
platters by heads, which all move back and forth as a unit reading from the circular tracks in the
platter. A cylinder is a set of corresponding tracks in a vertical slice throughout the disk, that can
be accessed simultaneously by all of the heads. A sector is a section of one disk (shaped like a
piece of pie) and the disk block is the intersection of a sector and a track.
To specify a certain byte on the disk we must determine which block it is in, which cylinder the
block is in, which sector the block is in and which head to use thus a block needs a triple
cylinder, head, sector (c,h,s) to identify it. It is easy to convert between CHS and LBA when given
the numbers of c, h & s.
At the start of every disk, there is partition information, at the start of every partition is the file
system information. These initial blocks of information are called the superblocks, kept at well
known points around the disk incase the main superblock gets trashed.When allocating blocks
for a file the file system should try to keep them close together. Fragmentation occurs when we
delete and recover its blocks, so there are the usual strategies for allocation (first fit etc.) with the
twist of physical location.
There are three main ways to access a file; read, write or run it as a program. For a directory
there are three main ways of access; read (list contents), write (edit contents) or search. Files
have owners and they inherit the userID of the process that created it, and there are also groups
of users. Groups allow access/denial to large numbers of people, and each user can be in more
than one group. Each file has a group ownership as well as a user ownership. Each file therefore
has a group of permission bits from the owner, the group owner, and everyone else, and for
each of read/write/execute access.
Access control lists (ACL’s) generalise the threepart User, Group, Other to arbitrary collections.
Basically a list of permissions attached to an object.
I/O devices range across human speed, machine speed, realtime.
Programmed; initiated by the program which then waits for the result.
Interrupt driven; initiated by the program which does something else until interrupted when the
I/O has finished.
Direct memory Acess (DMA); direct device to memory I/O transfer is started and the
processor is only interrupted when the I/O has finished
Synchronous; wait for the data to arrive after read request/wait for a write to finish after write
Asynchronous; set the read/write going and leave it until an interrupt is received when transfer
Each kind of peripheral needs code to access it (called a driver), some devices have standard
interfaces so we can use a single piece of code to access any disk, but some devices need
specifically written code that only works for that device, usually kept secret for intellectual
property. Drivers are part of the kernel, so they have access to the fill machine which can cause
bugs. Microkernels in some OS’s keep driver separate from the main kernel to remedy this by
using a different priority ring. Another approach is to have the main part of the driver in an
ordinary process and as little of the code in the kernel as possible, providing the most protection.
This does involve a lot of crossing the user/kernel divide which is expensive.
Another way to eliminate the cost of calling the kernel is to use buffering (reading a chunk of data
to a memory register before flushing and returning), which delays calling the kernel until a decent
amount of work can be done.
This idea can also be used for the I/O inside the kernel, as buffering smooths out peaks in I/O
demand, with the disk cache acting as a buffer. As the disk is central to data we need to make
sure it’s being used efficiently, and compared to the CPU it takes a long time for the heads to
read the disk. Reads and writes therefore take a long time for the disk, and must therefore be
managed carefully, using disk scheduling. Platter may be rotating fast but the latency (called
access time) is on the order of 10ms, which on a 1GHZ processor is 10 millions cycles. The
data might come off the disk at a fair rate but the time we have to wait for this to start is
considerate. Latency is caused by the time it takes for the heads to get into position (seek time)
and the time is takes the platters to rotate to get the right block under the heads (rotational
delay). We therefore need to minimise the physical movement of the disk. One way to do this is
schedule the disk requests into an order that needs the smallest amount of physical movement
from the disk. Scheduling types;
FIFO or no scheduling, access blocks in the order they are requested easy to compute,
blocks arranged in cluster so locality comes into play.
LIFO generally from the same process so for blocks that are likely to be related, not good for
Closest Block First pick request that minimises seek time, reduces seek time of FIFO by
50%, causes uneven access to outer blocks as heads hover in middle of disk
Elevator (or SCAN) as the heads go inwards/outwards serve the next nearest request in that
direction. Smooth head movements but biases to most recently covered or most outer cylinders.
Modern disks, have their own cache, and support tagged command queueing (TCQ) and native
command queueing (NCQ), which is basically disk drives doing their own scheduling as they
have a more accurate idea of the placement of the blocks than the OS does. We are seeing a
rise in solidstate disks (SSDs) which are just chunks of memory wired to look like disks to the
operating system, with faster read times and much less likely to break, but are more expensive
and have slow writing speeds and have a limited lifetime. To cope with the limited lifetime SSDs
have wear levelling technologies which redirect writes to a single block to blocks spread over the
entire device to increase the lifespan.
The Internet is a global collection of networks. An internet is just some collection of networks. An
intranet is a collection of networks owned by one organisation. Note; the web is NOT the internet.
The Internet is a collaboration between its member hosts, and data is passed through it from
source to destination by passing machine to machine called hops.
ARPA started as a project to connect all of their computers allowing the sharing of their
resources, being noncentralised to prevent single points of failure, so there would be multiple
paths between hosts. They could not send data through circuits as this would be too vulnerable,
so packet switching was advised. Packet switching is where data is chopped into small chunks
called packets and each packet is sent individually over different paths, and the receiving host
can construct the original data.
A packet has it’s destination address in, but relies on routers to direct it to this address. To
ensure interoperability, The Internet relies on standards and standardised protocols, so different
machines completely can still communicate and understand each other. The common language
of the internet is called the Transmission control Protocol/Internet Protocol (TCP/IP) which
helps communication over several layers. A layering model is just a recommendation on how to
approach the design of a standard, which we can then create implementations off.
There are two main layering models in use: the Open Systems Interconnection (OSI) seven
layer model, and the Internet four layer model the Internet (TCP/IP) model is used in the real
The layers of these models should be as self contained as possible this is modularity. They
should be easy to implement & understand, and only interface with neighbouring layers.
Layers of OSI model Physical deals with transmission of bits over a channel (voltages,
encoding of bits, which plugs, how many wires etc), Data link takes physical layer and tries to
create a channel with no errors in transmission , network controls the routing of data from
source to destination dealing with flow of control, transport accepts data from session layer and
arranges it into packets (packetisation) and from network layer into original data stream
(packetization), session manages sessions (set of exchanges) between source and
destination, presentation decides representation of data, and application contains protocols on
which applications that the application users can see are built. Data is passed from application
to hardware, being encapsulated (accurate transformation of data, in such a way that the layer
below can cope with it transparently) from layer to layer. For example there might be added an
identifying header, encoding bit patterns, put items in standard form etc.
Byte stuffing using extra characters to encode a stream of data correctly. Can cause epansion
of data, but makes the correct transmission of that data.
Internet model has four layers (TCP/IP) Link (OSI physical and data link layers) just says it
has to be capable of send and receiving IP packets, Network handles movement (routing) of
packets and the Internet Protocol (which is unreliable) is defined here, Transport provides flow
of data between source and destination and the transmission control protocol (TCP) and user
datagram protocol (UDP) are defined here, and Application (OSI session, presentation and app
layers) meaning Internet apps must take care over presentation issues.
Reliable protocols guarantee delivery (waits for lost packets to resend), and unreliable protocols
do not guarantee delivery (ignores lost packets).
Example: how an email might be transmitted over an Ethernet;
We start with the text of the email
The email application transforms the text using a MIME encoding (presentation)
The email application adds an envelope header (From, To,etc.)
TCP adds its header (reliability)
IP adds its header (routing)
Ethernet adds a header (local routing) and a trailer (checksum)
7. The bits are transformed using a 4B/5B encoding to smooth the bit patterns and are sent
using a threelevel electrical coding MLT3 (physical)
Comparing the two models; OSI model developed before implementation, Internet model after;
OSI makes clear distinction between model and implementation, OSI is general and can apply to
many systems (Internet is specific to TCP/IP), TCP/IP is successful and OSI is not. Problems
with the Internet model; specific to TCP/IP, merges data link and physical layers. The OSI model
is used but it’s protocols aren’t, and the TCP/IP’s model isn’t used but it’s protocols are.
There are several popular hardware implementations, the most popular being; ethernet wired
network, and WiFi wireless network. Ethernet uses carrier sense, multiple access with collision
detection (CSMA/CD) on a variety of speeds of hardware. Ethernet is a multiple access medium
(several hosts use the same wire to send data to one another), but if two hosts send
simultaneously there will be a collision, so the host must listen to the ethernet to see if anyone
else is using it carrier sense and after sending hosts listen for a collision collision detection.
If there is a collision each host wait a random amount of time (to prevent another collision) and
then retries with the carrier sense.
Hubs send an incoming signal to all of it’s outputs. Switches only send the input to the wire that
has the destination host.
Ethernet frame looks like;
IP addresses are hardware independent addresses.
ARP address resolution protocol, a linklayer protocol that given the IP address we can find the
corresponding ethernet address. There is then an ARP cache that records this relation which
can be used for the rest of the packets in the data transmission.
Gateway host machine on more than one network
Dynamic Host Configuration Protocol (DHCP) used by a machine to get an IP address, a
DHCP host returns an unused IP address back to the requesting host. Informs DHCP server
when finished with address. A Lease Time is the period of time that a host can use an IP
address for, and when it expires the client can use DHCP again and the client will get a new
lease for the existing address. DHCP can also give the address of the gateway host, name
servers, print servers, mail servers, and also lease times.
There are not enough IP addresses, as 32 bits are not enough (28 = 4 bil, not enough for 7 bil of
the world). Moving from IPv4 to IPv6 (128 bit address).
The names of websites correspond to an IP address, and a protocol called the domain name
system (DNS) uses servers to store the translation between IP addresses and website names.
Name servers are computers whose main purpose is to run DNS. DNS keep table mapping for
the domain, and help local hosts when they need to do a lookup of a nonlocal address.
Each reply from the server has a time to live attached to it, indicating how long the server should
keep the information before asking again. DNS does; A address name to IP address, PTR
pointer IP address to name, AAAA address name to IPv6 address, SOA start of authority
name to responsible name server, MX mail server name to mail server for that domain, etc.]
DNS is manymany relationship of names and address; one address can have many names and
many addresses can have one name. DNS is a fast and easy to manage protocol, so is very
LDAP (lightweight directory access protocol) general database (or directory) aimed at the
application layer, storing things like usernames, passwords, email addresses etc. and shares
many properties with DNS it’s distributed, can be replicated, & is hierarchical. Common use is
for a LDAP server of valid users on a network.
Secure sockets layer (SSL) protocol more modern version is the Transport layer security (TLS)
protocol, which provide secure communication over the internet. Layers on top of the transport
layer providing security & privacy, as well as authentication. It also prevents tampering, forgery &
SSL/TLS is used as a transport layer by applications, and it lives outside the kernel in the user
program space, and if a programmer wants security/authenticity, then they do a ssl/tls setup on
top of a normal TCP or UDP connection and uses ssl/tls reads and writes. SSL/TLS allows
authentication in both directions (server authenticates client & vis versa), and they can then go
on to negotiate a secure, private connection. Secure, but had overheads (but are not huge).
The Internet is successful in supplying services client makes a request and server returns
some data, e.g. DNS lookup LDAP, etc.
Remote Procedure Call (RPC) compute something on a different machine to offload it.
HyperText Transfer Protocol (HTTP) protocol used to request and return web pages.