Sei sulla pagina 1di 63

EE 472 / ECE 372Microprocessor

Interfacing andEmbedded Systems


Operating Systems
Lecturer: Manfred Mcke
Original material: James Peckol, Manfred Mcke

Contents

OS Motivation
OS History
OS Classification
Programs, tasks and processes, threads
Process/thread contexts
RTOS
A detailed view at Scheduling
Queues and TCBs
Example: A simple scheduler

OS Purpose
Enable effective use of computing infrastructure
by providing relevant services for organisation and execution
of applications (API).
off-loading functionality from application
higher level of abstraction

OS History I
Beginning: No OS
Programming by setting jumpers
Programming by punch cards
Output device: printer
Automate program input: Batch OS
Program read by a card-to-tape converter
Tape used as an input device to the computer
OS reads one Job after the other from the tape
Output written on tape

OS History II

OS History III
Dealing with slow input: Multiprogramming for better CPU usage
Memory partitioning
Load multiple programs in parallel
Run sequentially
Dealing with slow output: Spooling
simultaneous peripheral operations on-line
Output queue decouples resource and application

OS History IV
Dealing with slow users: Interactive time-sharing
Mainframe + 1 terminal / user
Terminal = standard input / standard output
Protection mechanisms, resource management
Multics (1965)
One of the first time-sharing OS
Concept of virtual memory
Developers: MIT, Bell Labs, General Electric

OS History V
UNICS (then Unix) - multitasking, multi-user
Motivation: Usable Multics, cross-development tool
Modular design, unified file system for IPC, shell script language
Firstly developed by Ken Thompson (former Bell employee) on a
PDP-7
C was designed by Dennis Ritchie as the programming language
for Unix
First 2 main derivatives developed (BSD - Berkeley Software
Distribution, System V AT&T)
De-facto standard for academia during late 70's and 80's
Linux = free open source x86 port of key Unix functionality

Historic OS Habitat

OS Classification I
By application domain
General Purpose
Windows, Unix, Linux, Android, OS X

Batch
Historical: OS/360, Today: Printers

Real-Time Operating System (RTOS)


QNX, RT Linux, FreeRTOS, Windows CE, Automotive: OSEK

Smartcard
MULTOS

OS Classification II
By features
Single user vs. multi user
Single-tasking vs. multi-tasking
By supported CPU
Distributed Desktop Embedded

OS Kernel Types

OS core, contains the most important functions


Process and data organisation (kernel space)
Calling a kernel function = System call
Kernel types:
Monolithic kernel (all functionality in kernel space)
Micro kernel (delegate functionality to servers)
Hybrid kernel

Our Focus

OS Terminology

Program (source code of some application)


Binary, executable (executable instance of some application)
Task (unit of execution, = process or thread on different OS)
Process (application instance being executed)
Thread (smallest code sequence manageable by OS
scheduler)
Job (executable program in batch context)
Task/process/thread context (relevant state)
Inter-process/task/thread communitation (IPC, ITC)
context switch / context switching
deterministic / non-deterministic
synchronous / asynchronous

What is a Task?
Typical embedded systems decompose their functionality into
smaller, independent (concurrent) programs
These programs work together in an organized way
Each of these programs is called a task when executed
A system that can handle multiple tasks is called a
multitasking system
-> A task is a unit of execution supported by
some multitasking system

Programs and Processes


What is a program? What is a process?
A process is a program in execution
A program is passive
A process is active

We have all worked with software programs. A program is a


static collection of code designed to perform some task
A process is the execution of a program, or part of a program,
operating sequentially one instruction at a time

Parts of a Process
A process is much more than just program code

Program counter which instruction is being executed


Contents of all the registers working values
Stack saved values, local variables, parameters, return
Data global variables (the heap)
Code instructions, this is the program

Some of this information is held in hardware registers or


cache, as well as memory
Many processes can be part of a single program
Each has its own context

Prepare a Meal for Friends


Evening With Friends

Set Menu

Prepare Stock

Prepare Meat

Add Veges

Season Meat

Manage Seasoning

Cook Meat

Clean Veges

Steam Veges

Clean Fruit

Season Fish

Puree Fruit

Prepare Sauce
Add Sugar

Steam Fish

[Needs Salt]
Simmer

Clean Fish

Prepare Garnish

Make Sauce

Adjust Flavoring

Add Salt
Put into Freezer
[Lightly Frozen]

Serve Soup

Reduce Sauce

Serve Veges

Serve Fish

Sereve Meat and Sauce

Eat

Enjoy Meal

Remove from Freezer and Serve

Multitasking
A multitasking design must support the operations:

Exchanging / sharing data between tasks


Synchronizing tasks
Scheduling the execution of tasks
Sharing resources between tasks

Many of these operations can become very complex for even


relatively simple multitasking systems
It would be nice if we had some software to take care of it for
us

Operating System
An Operating System (OS) is software that provides some kind
of task coordination
If the OS provides the functionality of specifying and meeting
time constraints it is called a real-time operating system
Every OS has three primary components to implement task
coordination:
Schedule
Dispatcher
Intertask communication

Operating System Components


Scheduler
Determines which tasks will run and when they will run

Dispatcher
Does everything required to start a task (context switch)

Intertask Communication
Exchange data and information between tasks on the same machine
or across machines.
Can also facility communication between tasks the OS

The portion of the OS that provides these services is called the


kernel

Other OS components
Most operating systems that we use are full featured
operating systems
Windows
Linux
OSX

Full featured operating systems include many other libraries


to support a range of functionality
Device drivers
Rich communication packages
Human computer interface support

Real Time Operating System (RTOS)


RTOS are special purpose operating systems designed to meet
rigid per-task completion time requirements
Can support either hard or soft real-time systems
Typically interact with the physical environment
Sensors or other measurement devices for input
Potentially some actuators or displays for output

Often involved in scientific apparatus or some control system


Real time = responsive (according to some specification)

Hard and Soft Real Time in RTOS


Hard Real Time
Delays are known or given an upper bound
Operating correctly if it returns within bounds

Soft Real Time


For RTOS, critical tasks get priority over other tasks
Retain their priority until completed

Real time tasks must eventually complete, typically, but not


always within time constraints
RTOS is good for mixing with other systems

Process Creation
When a process is created it is allocated resources by the
system or OS, potentially including:

Stack
Memory address space
Registers (on the CPU)
Program counter
I/O ports
Network connections
File descriptors, etc.

On an embedded system these resources are typically not


shared

CPU as a Resource
Traditional view of computing focuses on the program, not
the process
You talk about a program running on the computer, or maybe
tasks within the program
For embedded application, we need a different point of view
The microprocessor is the center, not the program

CPU as a Resource (cont.)


CPU is simply another resource, available for use by the
process to do its job
When a task enters the system
Takes up memory
Uses other resources

Persistence
Time to complete task is called execution time
Time from entering the system to terminating (finishing) is
called the persistence of a task

Limited Resources
For a single process in the system, no contention for resources
It can run for as long as it wants
Use as much memory as it wants
Use all other resources freely

When more tasks are added to the system, there can be a


contention problem
Generally only one CPU in embedded, other resources often very
limited

Resolving Contention
Contention can be resolved by carefully managing how
ressources are allocated to processes
Usually limit the time process can use resource

Through sharing, each process can complete


Sharing the CPU between processes quickly can give the
appearance of both executing at once
Simulates parallel execution with a single processor
This scheme is called multitasking and tasks are said to be
running concurrently (really: time-multiplexed)

Implementing Control
If the CPU is a resource -> most important resource
Processes also share
Timers
I/O units
Busses

Despite apparent simultaneity


Only one process really running at a time

This processes is in the run state


Other processes are in the ready waiting state

Process State
A system with three processes
One is always running, other two waiting for CPU

Must decide
Which process gets the CPU
When the task gets the CPU

Solution
Schedule

Schedule
The schedule determines
When a process gets the CPU
Under what conditions the process gets the CPU
How long the process can use CPU and other resources

Collectively, the criteria for making these decisions is called


the scheduling strategy

Schedule Strategy
For embedded systems there are three
Multiprogramming
Real-time
Time-sharing

Multiprogramming
Running task continues until it requires an external input
This includes waiting for I/O event or timer

Real-time
Task with specific deadlines
Guaranteed to complete before deadline expires
Systems that require a response to event within well defined time
limits or constraints use this system
Hard real-time

Schedule Strategy (cont.)


Time-sharing
Running processes is required to give up CPU after a specific period of
time, regardless of completion
Hardware timer used to preempt the current executing process and
return control to the OS
This system ensures fairness because all processes are guaranteed
some execution time

Context
A tasks context comprises important information about the
state of the task;
such as:
the values of any variables held in the CPUs registers
the value of PC (program counter)
and so on

Process State - Switching Context


Process is part of an executing program, always in one of
many potential states, including:

New Just created


Running Instructions from this process being executed
Waiting Waiting for some extern event, usually I/O
Ready Can be run at any time
Terminated Execution has finished

Each time a process is preempted or blocked the next task that


is ready begins to run
This requires a context switch

Context Switch
Upon context switch
State of running process is saved
State of new process is restored and execution of this process
continues from where it left off
Only for process that was previously running

Context switches require many instructions and can take a


significant amount of time to complete

Schedule with Context Switches


Process states now including new tasks, tasks that are
preempted and terminating tasks
Multiprogrammed
system, objective is
to always have some
process running
This maximizes the
CPU usage

Threads
Task or process characterized by resources required to execute
that portion of the program
A thread is the smallest subset of resources required to
execute a program
Includes all CPU registers, including PC
Program stack

This is a subset of all process resources so it is called a


lightweight thread
Doesnt include I/O, timers and so on

The process itself is a heavyweight thread

Threads (cont.)
A thread can only be in one process
Processes without
a thread cant do
anything
A single thread
sequentially executes
a set of instructions
Called thread of
execution or control

Status

Resources

Stack

Thread

Firmware
(Address Space)

CPU

Data
(Address Space)

Single Thread
Thread has a stack and status information, including copy of
registers (lightweight context)
Uses, but does not contain

Code (firmware)
Data
CPU (and the physical registers)
Other process resources

This is a single process -> single thread design


Process state (running, blocked, ready ) is actually thread
state
For embedded, may have many processes consisting of a single
sequential program. This is multi process -> single thread

Multiple Threads
More complicated embedded systems perform a single
primary function, using related operations
During partitioning and functional decomposition, identify
which parts can use parallel execution
Could have one task for each type of I/O

At runtime, process can pass the CPU around to each of its


subtasks, allowing it to do many jobs

Multiple Threads (cont.)

This is called single process -> multithread design


Unlike processes,
threads are not
independent
Status
Threads can access
Status
Status
Stack
any address within
Thread
Stack
Stack
the process
Thread
Thread
This includes the
stack of other threads
Firmware
Data
Context switch
(Address Space)
(Address Space)
between threads is
much easier and fast

Resources

CPU

Multiple Threads
Threads are useful because switching is so fast
Much less information is saved and restored on switch
An operating system supporting tasks with multiple threads is
a multithreaded operating system
Can easily extend this design to support multiple separate
process as well, each with its own threads
This is called multiprocess-> multithread design

Memory Resource Management


Memory is most important resource after CPU
Most microprocessors still von Neumann architecture,
program is same as other data
Firmware
Can have single or separate
Supervisory Mode
physical memory
Address Space
Shared memory bus
can be a bottleneck!

Multiple processes cannot


access the memory of
other processes, due to OS

Supervisor Mode
Access
User Mode
Address Space

User Mode
Access

Layering and Virtual Machines


Most contemporary operating systems
Implemented using a layered approach

Main advantage is
increased modularity
Layers are designed such
that each layer
Uses functions / operations
and services of lower layers

Typical architecture appears


as Operating System Virtual
Machine Model

(Embedded)
Application
Command Interface
System I/O
System and User
Memory Management
Intertask
Communication
CPU and Resource
Scheduling / Dispatching
Thread Management
Microprocessor Hardware
and
Hardware Resources

Layering and Virtual Machines (cont.)


VM = Look like some other platform to application
Sometimes higher level layers have access to lower levels
System calls
Hardware instructions

With such capability


Tune Virtual machine
for performance

-> Hard to implement,


-> Requires extensive
cross layer knowledge
Very hot topic (Cloud, VMWare, )

(Embedded)
Application

Command Interface
System I/O
System and User
Memory Management
Intertask
Communication
CPU and Resource
Scheduling / Dispatching
Thread Management
Microprocessor Hardware
and
Hardware Resources

Job Queue
Process entering system is put into the job queue
All jobs in the system are contained in the queue, including
system jobs and user jobs
Ready and waiting processes are in ready queue
Can be other queues, including those for resources
Processes waiting for a resource are on device queue

Task (Process) Control Block (TCB) stores information about


each task
TCBs typically stored in a linked list

Task Control Block (TCB)


In a task based approach, each process represented by the OS
in a TCB data structure
TCB contains all the important
State
Pointer
information about the task

Pointer (to next TCB in queue)


Process ID and state
PC and other registers (context)
Scheduling information (priority)
Memory information (tag and cache)
I/O status (allocated resources)

Process ID

Program Counter
Register Contents

Memory Limits
Open Files
Etc.

Static TCB Allocation


Static allocation is often used in embedded systems with no
memory management (i.e., no malloc())
There are a fixed number of TCBs in system and memory for
TCBs allocated at compile time
When a task is initiated

Empty TCB taken from list and populated


TCB is placed into ready state by scheduler
Moved to execute state by dispatcher
Upon termination, TCB returns to dormant state

Programmer must be careful not to use up all TCBs

Dynamic TCB Allocation


With dynamic allocation, there are a variable number of TCBs
allocated from the heap at runtime
When a task is initiated

TCB created, populated with appropriate information


TCB is placed into ready state by scheduler
Moved to execute state by dispatcher
When task terminates, TCB memory is freed to heap

Creating TCBs is more expensive, but allows for more TCBs


and saves memory if there are few TCBs
Only possible if there is a memory manager

Task Queue
When a task enters the system it is placed into the Entry
Queue or Job Queue
Easiest way to implement queue is with a linked list data
structure
List node data contains TCBs
Each TCB points to the next TCB in the queue

Can also use an array to hold TCBs


Each entry must look exactly alike
This imposes some limits on system, but we can work around them

TCB in C
TCB is implemented as a struct which
Contains pointers to all relevant task information

Because data members of a struct must be the same for all


instances of that struct
We use void* pointers to point to task specific types

TCB struct must include, at a minimum


OS bookkeeping information
Task pointer
Task data and context

TCB C Example
Here is an example TCB in C

A Simple Kernel
3 simple jobs are scheduled and performed
Bring in some data
Perform a computation on the data
Display the data

Each task will run to completion!


2 ways of implementation
A simple queue (Example 11.0)
A TCB (Example 11.1)
Increment
2.0
Get
1.0
Remote Input

Data Buffer

Display
3.0

Remote Output

Example 11.0
// Building a simple OS kernel - step 1
#include <stdio.h>
// Declare the prototypes for the tasks
void get (void* aNumber);
// input task
void increment (void* aNumber); // computation task
void display (void* aNumber); // output task
void main(void)
{ int i=0;
// queue index
int data;
// declare a shared data
int* aPtr = &data;
// point to it
void (*queue[3])(void*);
// declare queue as an array of pointers to
// functions taking an arg of type void*
queue[0] = get;
// enter the tasks into the queue
queue[1] = increment;
queue[2] = display;

Example 11.0 (cont.)


while(1)
{ queue[i] ((void*) aPtr); // dispatch each task in turn
i = (i+1)%3; }
return;
}
void get (void* aNumber) // perform input operation
{ printf ("Enter a number: 0..9 ");
*(int*) aNumber = getchar();
getchar();
// discard cr
*(int*) aNumber -= '0; // convert to decimal from ascii
return; }
void increment (void* aNumber) // perform computation
{ int* aPtr = (int*) aNumber;
(*aPtr)++;
return; }
void display (void* aNumber)
// perform output operation
{ printf ("The result is: %d\n", *(int*)aNumber);
return; }

Example 11.1
// Building a simple OS kernel - step 2
#include <stdio.h>
// Declare the prototypes for the tasks
void get (void* aNumber);
// input task
void increment (void* aNumber); // computation task
void display (void* aNumber);
// output task
// Declare a TCB structure
typedef struct
{
void* taskDataPtr;
void (*taskPtr)(void*);
} TCB;
void main(void)
{
int i=0;
// queue index
int data;
// declare a shared data
int* aPtr = &data; // point to it
TCB* queue[3];

// declare queue as an array of pointers to TCBs

Example 11.1 (cont.)


// Declare some TCBs
TCB inTask;
TCB compTask;
TCB outTask;
TCB* aTCBPtr;
// Initialize the TCBs
inTask.taskDataPtr = (void*)&data;
inTask.taskPtr = get;
compTask.taskDataPtr = (void*)&data;
compTask.taskPtr = increment;
outTask.taskDataPtr = (void*)&data;
outTask.taskPtr = display;
// Initialize the task queue
queue[0] = &inTask;
queue[1] = &compTask;
queue[2] = &outTask;

Example 11.1 (cont.)


// schedule and dispatch the tasks
while(1)
{
aTCBPtr = queue[i];
aTCBPtr->taskPtr( (aTCBPtr->taskDataPtr) );
i = (i+1)%3;
}
return;
}

Example 11.1 (cont.)


void get (void* aNumber)
// perform input operation
{
printf ("Enter a number: 0..9 ");
*(int*) aNumber = getchar();
getchar();
// discard cr
*(int*) aNumber -= '0';
// convert to decimal from ascii
return;
}
void increment (void* aNumber)
{
int* aPtr = (int*) aNumber;
(*aPtr)++;
return;
}

// perform computation

void display (void* aNumber)


// perform output operation
{
printf ("The result is: %d\n", *(int*)aNumber);
return;
}

Homework
What advantage do you see in using a TCB (Code 11.1) compared to
the approach in Code 11.0 (max. 2 sentences)?
What are the potential problems in the 2 code examples (list, max.
50 words in total)?
Install C compiler (if necessary), compile code on PC
Add automatic data source (rand()) to replace manual input
Instrument code for profiling (either by adding some timing
functionality or by using the integrated profiler, if available).
Report min/mean/max execution time per task 1/2/3
(100.000 iterations)
Hand in till Monday at midnight

Potrebbero piacerti anche