Starting and stopping programs and sharing the CPU between them.
Process: a program in execution. process execution must progress in sequential fashion
An operating system executes a variety of programs:
jobs
user programs
or tasks
Process 和 Program 的关系
A process is considered an ‘active’ entity, a program is considered to be a ‘passive’ entity. Program becomes process when executable file loaded into memory.
As a process executes, it changes state. The state of a process is defined in part by the current activity of that process
new
: The process is being createdrunning
: Instructions are being executedwaiting
: The process is waiting for some event to occurready
: The process is waiting to be assigned to a processorterminated
: The process has finished executionProcess Control block is a data structure used for storing the information about a process, It is also called as context of the process
进程控制块是为了管理进程设置的一个数据结构。是系统感知进程存在的唯一标志。
Each & every process is identified by its own PCB
PCB of each process resides in the main memory
PCB of all the processes are present in a linked list
PCB is important in multiprogramming environment as it captures the information pertaining to the number of processes running simultaneously
Process scheduler selects from among the processes in memory that are ready to execute, and allocates the CPU to one of them
Maintains scheduling queues of processes:
Job queue
: set of all processes in the systemReady queue
: set of all processes residing in main memory, ready and waiting to executeDevice queues
: set of processes waiting for an I/O deviceLong-Term Scheduler
: Also called Job Scheduler
and is responsible for controlling the Degree of Multiprogramming
Short-Term Scheduler
: Also known as CPU scheduler
and is responsible for selecting one process from the ready state for scheduling it on the running state
Medium-Term Scheduler
: Responsible for swapping of a process from the Main Memory to Secondary Memory and vice-versa (mid-term effect on the performance of the system). It can be added if degree of multiple programming needs to decrease.
Queueing Diagram for Scheduling
Queueing diagram represents queues, resources, flows
When CPU switches to another process, the system must save the state of the old process and load the saved state for the new process via a context switch. Context of a process represented in the PCB
System must provide mechanisms for:
Parent process create children processes, which, in turn create other processes, forming a tree of processes
Resource sharing options:
Execution options:
Process executes last statement and then asks the operating system to delete it using the exit() system call:
Parent may wait terminate the execution of children processes.
Independent Processes
: neither affect other processes or be affected by other processesCooperating Processes
: can affect or be affected by other processes. There are several reasons why cooperating processes are allowed:
Information Sharing
: Processes which need access to the same file for exampleComputation speedup
: A problem can be solved faster if the problem can be broken down into sub-tasks to be solved simultaneouslyModularity
: Break a system down into cooperating modules.Convenience
: Even a single user may be multi-tasking, such as editing, compiling, printing, and running the same code in different windowsMessage passing
communication takes place by way of messages exchanged among the cooperating processes.
A message-passing facility provides at least two operations:
The message size is either fixed or variable
If processes P and Q want to communicate, then a communication link must exist between them.
There are several methods for logically implementing a link and the send()/receive() operations:
Direct or indirect communication
Direct Communication
: Processes must name each other explicitly. Direct Communication is implemented when the procsses use specific process identifier for the communication, but it is hard to identify the sender ahead of time. e.g. send(P, message)
mains send a message to process P
Indirect Communication
: create a new mailbox (port), send and receive messages through mailbox, then destroy a mailbox. e.g. send(A, ,message)
mains send a message to mailbox A.
Synchronous or asynchronous communication
Message passing may be either blocking
or non-blocking
. Blocking is considered synchronous: and non-blocking is considered asynchronous.
Automatic or explicit buffering
Shared-Memory Systems
a region of memory is shared by cooperating processes, processes can exchange information by reading and writing all the data to the shared region.
Two types of buffers can be used:
unbounded-buffer
: places no practical limit on the size of the bufferbounded-buffer
: assumes that there is a fixed buffer sizeA thread is an independent stream of instructions that can be scheduled to run by the OS. (OS view)
A thread can be considered as a “procedure” that runs independently from the main program. (Software developer view)
进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。
线程:是进程的一个执行单元,是进程内可调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。
协程 (cooperative routine, cooperative tasks):是一种比线程更加轻量级的存在。一个线程也可以拥有多个协程。其执行过程更类似于子例程,或者说不带返回值的函数调用。
例程:就是函数,笑死
进程 和 线程 的区别
python 多线程的问题
由于历史遗留的问题,严格说多个线程并不会同时执行(没法有效利用多核处理器,python
的并发只是在交替执行不同的代码)。多线程在 python
中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。所以 python
的多线程并发并不能充分利用多核,并发没有 java
的并发严格。(所以说 python
并不严谨)
原因:
原因就在于 GIL ,在 Cpython 解释器(python
语言的主流解释器)中,有一把全局解释锁(GIL, Global Interpreter Lock),在解释器解释执行 python
代码时,任何 python
线程执行前,都先要得到这把 GIL 锁。这个 GIL 全局锁实际上把所有线程的执行代码都给上了锁。
这意味着,其它线程要想获得 CPU 执行代码指令,就必须先获得这把锁,如果锁被其它线程占用了,那么该线程就只能等待,直到占有该锁的线程释放锁才有执行代码指令的可能。
什么时候 GIL 被释放?
python
虚拟机的指令),也会释放 GIL。即,每执行100条字节码,解释器就自动释放 GIL 锁,让别的线程有机会执行。python
虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个 python
进程有各自独立的 GIL 锁,互不影响。
Benefits
Thread Control Block
Threads are scheduled on a processor, and each thread can execute a set of instructions independent of other processes and threads. Thread Control Block stores the information about a thread. It shares with other threads belonging to the same process its code section, data section and other operating-system resources, such as open files and signals.
Life Cycle
Concurrency means multiple tasks which start, run, and complete in overlapping time periods, in no specific order
A system is parallel if it can perform more than one task simultaneously.
并发和并行的区别
Multithreading can be supported by:
User level libraries (without Kernel being aware of it): Library creates and manages threads (user level implementation)
User thread is the unit of execution that is implemented by users and the kernel is not aware of the existence of these threads. User-level threads are much faster than kernel level threads. All thread management is done by the application by using a thread library. 用户级线程到底有什么用?
Advantages:
Disadvantages:
Kernel level: Kernel creates and manages threads (kernel space implementation)
Kernel thread is the unit of execution that is scheduled by the kernel to execute on the CPU. are handled by the perating system directly and the thread management is done by the kernel.
Advantages:
Disadvantages:
4. Thread switching always involves the kernel. This means 2 mode switches per thread switch
5. So, it is slower compared to User Level Threads, but faster than a full process switch
A relationship must exist between user threads and kernel threads. That is, mapping user level threads to kernel level threads.
In a combined system, multiple threads within the same application can run in parallel on multiple processors.
Multithreading models are three types:
No matter which thread is implemented, threads can be created, used, and terminated via a set of functions that are part of a Thread API
Thread library provides programmer with API for creating and managing threads. Programmer just have to know the thread library interface. Threads may be implemented in user space or kernel space. library may be entirely in user space or may get kernel support for threading
Three primary thread libraries: POSIX threads, Java threads, Win32 threads
Two approaches for implementing thread library:
Explicit threading: the programmer creates and manages threads.
Implicit threading: the compilers and run-time libraries create and manage threads.
Three alternative approaches for designing multithreaded programs:
There are a variety of issues to consider with multithreaded programming
fork() system call
Creating a thread is done with a fork() system call. A newly created thread is called a child thread, and the thread that is initiated to create the new thread is considered a parent thread.
exec() system call
The exec() system call family replaces the currently running thread with a new thread. The original thread identifier remains the same, and all the internal details, such as stack, data, and instructions. Then the new thread replaces the executables
If exec() will be called after fork(), there is no need to duplicate the threads. They will be replaced anyway.
If exec() will not be called, then it is logical to duplicate the threads. so that the child will have as many threads as the parent has.
A signal is a software interrupt, or an event generated by a Unix/Linux system in response to a condition or an action. There are several signals available in the Unix system. The signal is handled by a signal handler (all signals are handled exactly once).
asynchronous signal is generated from outside the process that receives it
synchronous signal is delivered to the same process that caused the signal to occur
Terminating a thread before it has finished.
Two general approaches:
Asynchronous cancellation terminates the target thread immediately
Deferred cancellation allows the target thread to periodically check if it should be cancelled. Cancelled thread has sent the cancellation request
Many programs are written as a single threaded process.
If we try to convert a single-threaded process to multi-threaded process, we have to be careful about the following:
PS is the task of coordinating the execution of processes in a way that no two processes can have access to the same shared data and resources. Because concurrent access to shared data may result in data inconsistency.
Maintaining data consistency requires mechanisms to ensure the orderly execution of cooperating processes
Race condition
: The situation where several processes access and manipulate shared data concurrently. The final value of the shared data depends upon which process finishes last. To prevent race conditions, concurrent processes must be synchronized
Each (concurrent) process has a code segment, called Critical Section (CS), in which the shared data is accessed. When using critical sections, the code can be broken down into the following sections:
Race condition updating a variable
Critical section to prevent a race condition
Multiprogramming allows logical parallelism, uses devices efficiently but we lose correctness when there is a race condition. So, we forbid/deny logical parallelism inside critical section, so we lose some parallelism, but we regain correctness.
关于临界区
Solutions to CS problem
There are 3 requirements that must stand for a correct solution:
Framework for analysis of solutions
Each process executes at nonzero speed but no assumption on the relative speed of n processes. No assumptions about order of interleaved execution. The central problem is to design the entry and exit sections
It was formulated by Gary L. Peterson in 1981. Only 2 processes, P0 and P1
Processes may share some common variables to synchronize their actions.
int turn; // indicates whose turn it is to enter the critical section.
boolean flag[2]; // initialized to FALSE,
// indicates when a process wants to enter into their CS.
// flag[i] = true implies that process Pi is ready (i = 0,1)
NEED BOTH the turn
and flag[2]
to guarantee Mutual Exclusion, Boundedwaiting, and Progress.
Proof of Correctness
Drawbacks of Software Solutions
Single-processor environment
could disable interrupts Effectively stops scheduling other processes. Currently running code would execute without preemption
satisfy the mutual exclusion requirement, but do not guarantee bounded waiting.
Multi-processor environment
modern machines provide special atomic hardware instructions. Atomic mean non-interruptable (i.e., the instruction executes as one unit)
Advantages
Disadvantages
Busy-waiting
is employed, thus while a process is waiting for access to a critical section it continues to consume processor timeStarvation
is possible when a process leaves a critical section, and more than one process is waitingDeadlock
is possible if a low priority process has the critical region and a higher priority process needs, the higher priority process will obtain the processor to wait for the critical regionMutex Lock / Mutual exclusion
Mutex is a software tool. It allows multiple process / thread to access a single resource but not simultaneously.
To enforce mutex at the kernel level and prevent the corruption of shared data structures: disable interrupts for the smallest number of instructions is the best way.
To enforce mutex in the software areas: use the busy-wait mechanism. busy-wait mechanism
or busy-looping
or spinning
is a technique in which a process/thread repeatedly checks to see if a lock is available.
using mutexes is to acquire a lock prior to entering a critical section, and to release it when exiting
Mutex object is locked or unlocked by the process requesting or releasing the resource.
This type of mutex lock is called a spinlock because the process “spins” while waiting for the lock to become available.
Semaphore
Semaphore was proposed by Dijkstra in 1965 which is a technique to manage concurrent processes by using a simple integer value. Semaphore is a integer variable which is non-negative and shared between threads.
This variable is used to solve the critical section problem and to achieve process synchronization in the multiprocessing environment. It is accessed only through two standard atomic operations: wait()
and signal()
.
To allow k processes into CS at a time, simply initialize mutex to k.
There are two main types of semaphores:
COUNTING SEMAPHORE: allow an arbitrary resource count. Its value can range over an unrestricted domain. It is used to control access to a resource that has multiple instances.
The semaphore S is initialized to the number of available resources. Each process that wishes to use a resource performs a wait() operation on the semaphore. When a process releases a resource, it performs a signal() operation. When the count for the semaphore goes to 0, all resources are being used. After that, processes that wish to use a resource will block until the count becomes greater than 0.
BINARY SEMAPHORE: This is also known as mutex lock. It can have only two values: 0 and 1. Its value is initialized to 1. It is used to implement the solution of critical section problem with multiple processes.
Starvation and Deadlock
Starvation and Deadlock are situations that occur when the processes that require a resource are delayed for a long
time.
Deadlock is a condition where no process proceeds for execution, and each waits for resources that have been acquired by the other processes. In Starvation, process with high priorities continuously uses the resources preventing low priority process to acquire the resources.
The mutex binary semaphore provides mutual exclusion for accesses to the buffer pool and is initialized to the value 1. The empty and full semaphores count the number of empty and full buffers. The semaphore empty is initialized to the value n, the semaphore full is initialized to the value 0.
生产者消费者问题
A data set is shared among a number of concurrent processes. Only one single writer can access the shared data at the same time, any other writers or readers must be blocked. Allow multiple readers to read at the same time, any writers must be blocked.
读者写者问题
How to allocate several resources among several processes. Several solutions are possible:
哲学家进餐问题
Process execution consists of a cycle of CPU execution and I/O wait. Process execution begins with a CPU burst, followed by an I/O burst, then another CPU burst .etc. An I/O-bound program would typically have many short CPU bursts, A CPU-bound program might have a few very long CPU bursts. This can help to select an appropriate CPU-scheduling algorithm.
The duration of these CPU burst have been measured.
I/O bound
Has small bursts of CPU activity and then waits for I/O.
Affects user interaction (we want these processes to have highest priority)
CPU bound
Hardly any I/O, mostly CPU activity, useful to have long CPU bursts. Could do with lower priorities.
The CPU scheduler is the mechanism to select which process has to be executed next and allocates the CPU to that process. Schedulers are responsible for transferring a process from one state to the other.
Basically, we have three types of schedulers:
Scheduler triggered to run when timer interrupt occurs or when running process is blocked on I/O. Scheduler picks another process from the ready queue. Performs a context switch.
Preemptive scheduling
the system may stop the execution of the running process and after that, the context switch may provide the processor to another process. The interrupted process is put back into the ready queue and will be scheduled sometime in future, according to the scheduling policy
Non-preemptive scheduling
when a process is assigned to the processor, it is allowed to execute to its completion, that is, a system cannot take away the processor from the process until it exits.
Any other process which enters the queue has to wait until the current process finishes its CPU cycle
CPU scheduling takes place on 4 circumstances:
Scheduling under 2 and 4 is nonpreemptive - a new process must be selected. All other scheduling is preemptive (either continue running the current process or select a different one).
Dispatcher module gives control of the CPU to the process selected by the short-term scheduler. This involves:
Dispatch latency: time it takes for the dispatcher to stop one process and start another running. Dispatcher is invoked during every process switch; hence it should be as fast as possible
Order of scheduling matters
Terms the algorithms deal with:
Poor in performance as average wait time is high
Advantages:
Disadvantages:
Determining Length of Next CPU Burst
No way to know exact length of process’s next CPU burst. But it can be estimated by using lengths of past bursts: next = average of all past bursts
Exponential averaging: next = average of (past estimate + past actual)
Let t n t_n tn = actual length of the n t h n^{th} nth burst. τ n \tau_n τn = predicted value for the next CPU burst. 0 ≤ a ≤ 1 0\le a\le1 0≤a≤1 = weighing factor. The estimate of the next CPU burst period is: τ n + 1 = a t n + ( 1 − a ) τ n \tau_{n+1}=at_n+(1-a)\tau_n τn+1=atn+(1−a)τn
Commonly, a = 1 2 a=\frac12 a=21. If a = 0 a=0 a=0, then recent history has no effect. If a = 1 a=1 a=1, then only the most recent CPU bursts matter.
If a new process arrives with a shorter burst time than remaining of current process, then schedule new process
Further reduces average waiting time and average response time
Context Switch - the context of the process is saved in the Process Control Block PCB when the process is removed from the execution and the next process is scheduled. This PCB is accessed on the next execution of this process.
Each process is assigned a priority
The CPU is allocated to the process with the highest priority (smallest integer = highest priority)
Priorities may be:
problem:
low priority processes may never execute
solution:
Aging: as time progresses increase the priority of the process
Each process gets a small unit of CPU time (time quantum or time-slice), usually 10-100 milliseconds. After this time has elapsed, the process is preempted and added to the end of the ready queue Ready queue is treated as a circular queue
If there are n n n processes in the ready queue and the time quantum is q q q, then each process gets 1 n \frac1n n1 of the CPU time in chunks of at most q q q time units at once. No process waits more than ( n − 1 ) q (n-1)q (n−1)q time units
q q q large: RR scheduling = FCFS scheduling
q q q small: q q q must be large with respect to context switch, otherwise overhead is too high
Ready queue is partitioned into separate queues.
将系统中的进程就绪队列从一个拆分为若干个,将不同类型或性质的进程固定分配在不同的就绪队列,不同的就绪队列采用不同的调度算法,一个就绪队列中的进程可以设置不同的优先级,不同的就绪队列本身也可以设置不同的优先级。
多级队列调度算法由于设置多个就绪队列,因此对每个就绪队列就可以实施不同的调度算法,因此,系统针对不同用户进程的需求,很容易提供多种调度策略。
foreground (interactive) processes: May have externally defined priority over background processes
background (batch) processes: Process permanently associated to a given queue; no move to a different queue
There are two types of scheduling in multi-level queue scheduling:
Must schedule among the queues too (not just processes):
The various categories of processes can be:
automatically place processes into priority levels based on their CPU burst behavior
多级反馈队列调度算法既能使高优先级的作业得到响应又能使短作业(进程)迅速完成。UNIX 就是采取的这种算法。
I/O-intensive processes will end up on higher priority queues and CPU-intensive processes will end up on low priority queues. A process can move between the various queues (aging can be implemented this way).
A multilevel feedback queue uses two basic rules:
Multilevel-feedback-queue scheduler defined by the following parameters:
e.g.
Three queues:
Scheduling:
FCFS, RR, Priority Scheduling 算法的 C++ 模拟实现:
#include
#include
#include
using namespace std;
//进程状态,这里增加一种,表示虽然输入,但还没有进入系统
enum STATE{
Executing,
Ready,
Finish,
Unarrive
};
char* StateString[] = {"Executing", "Ready", "Finish", "--"};
struct PCB {
int ID;
int priority; //值越小,优先级越高
int arrivalTime;
int burstTime;
int responseTime;
int completionTime;
int remainTime;
STATE state;
};
bool cmp_ready_time(const PCB a, const PCB b) {return a.arrivalTime < b.arrivalTime;}
bool cmp_priority(const PCB a, const PCB b) {
if (a.priority != b.priority) return a.priority < b.priority;
else return a.arrivalTime < b.arrivalTime;
}
PCB *running_process = NULL; //当前运行任务
vector<PCB> inputQue; //进程输入队列,如当前时刻小于进程到达时间,则该进程仍然在输入队列中
vector<PCB> readyQue;
vector<PCB> terminalQue;
int select_algorithm()
{
printf("\nSelect a scheduling algorithm(input 1、2、3 to choose):\n");
printf("1. FCFS\n");
printf("2. Round-Robin\n");
printf("3. DynamicPriority\n");
int n;
while (scanf("%d",&n))
{
if (n>3 || n<1) printf("please input again\n");
else break;
}
return n;
}
void input_process()
{
int num = 0;
printf("please input the number of processes:");
scanf("%d",&num);
PCB proc;
for (int i=0; i<num; i++)
{
printf("\nplease input the arrivalTime, burstTime and priority of %dth processes:\n",i);
scanf("%d%d%d", &proc.arrivalTime, &proc.burstTime, &proc.priority);
proc.ID = i;
proc.remainTime = proc.burstTime;
proc.responseTime = -1;//开始时间、结束时间默认为-1,表示尚未被调度过
proc.completionTime = -1;
proc.state = Unarrive;
inputQue.push_back(proc);
}
sort(inputQue.begin(), inputQue.end(), cmp_ready_time);
}
void print_process(PCB* proc)
{
if (proc == NULL) return;
printf("%-3d|%-12d|%-10d|%-10d|%-7s|%-14d|%-14d|%d\n", proc->ID, proc->arrivalTime, proc->burstTime,
proc->priority, StateString[proc->state],
proc->responseTime, proc->completionTime, proc->remainTime);
}
void print_all(int current)
{
if (current == -1)
printf("\n\n\n\nInitial process status: %d\n", current);
else
printf("\n\n\n\nThe current time is: %d\n", current);
printf("\nrunning process:\n");
printf("ID |arrivalTime |burstTime |priority |state |responseTime |completionTime|remainTime\n");
if (running_process != NULL){
print_process(running_process);
}
vector<PCB>::iterator it;
printf("\nprocess in ready_queue: \n");
printf("ID |arrivalTime |burstTime |priority |state |responseTime |completionTime|remainTime\n");
for (it=readyQue.begin(); it!=readyQue.end(); it++)
print_process(&(*it));
printf("\nprocess in terminal_queue: \n");
printf("ID |arrivalTime |burstTime |priority |state |responseTime |completionTime|remainTime\n");
for (it=terminalQue.begin(); it!=terminalQue.end(); it++)
print_process(&(*it));
printf("\nprocess in input_queue: \n");
printf("ID |arrivalTime |burstTime |priority |state |responseTime |completionTime|remainTime\n");
for (it=inputQue.begin(); it!=inputQue.end(); it++)
print_process(&(*it));
}
void proc_ready(int chip)
{
while (!inputQue.empty())
{
PCB proc = inputQue[0];
if (proc.arrivalTime <= chip)
{
proc.state = Ready;
readyQue.push_back(proc);
inputQue.erase(inputQue.begin() + 0);
}
else return;
}
}
bool proc_start(int chip)
{
running_process = new PCB;
*running_process = readyQue[0];
readyQue.erase(readyQue.begin() + 0);
if (running_process->responseTime == -1)
{
running_process->responseTime = chip;
}
running_process->state = Executing;
return false;
}
bool proc_finish(int chip)
{
running_process->completionTime = chip;
running_process->state = Finish;
terminalQue.push_back(*running_process);
delete running_process;
running_process = NULL;
return true;
}
void context_switch()
{
running_process->state = Ready;
readyQue.push_back(*running_process);
delete running_process;
running_process = NULL;
return true;
}
void FCFS()
{
int chip = 0;
//需要调度标志,默认为true
bool need_schedule = true;
while (running_process || !inputQue.empty() || !readyQue.empty())
{
proc_ready(chip);
if (need_schedule && !readyQue.empty())
need_schedule = proc_start(chip);
print_all(chip);
chip += 1;
if (running_process)
{
running_process->remainTime -= 1;
if (running_process->remainTime == 0)
need_schedule = proc_finish(chip);
else need_schedule = false;
}
}
print_all(chip);
}
void RR(int quantum)
{
int chip = 0;
bool need_schedule = true;
while (running_process || !inputQue.empty() || !readyQue.empty())
{
proc_ready(chip);
if (need_schedule && !readyQue.empty())
need_schedule = proc_start(chip);
print_all(chip);
chip += 1;
if (running_process)
{
running_process->remainTime -= 1;
if (running_process->remainTime == 0)
need_schedule = proc_finish(chip);
else if (chip % quantum == 0)
{
if (!readyQue.empty())
need_schedule = context_switch();
else need_schedule = false;
}
}
}
print_all(chip);
}
//动态优先级算法
void dynamic_priority()
{
int chip = 0;
bool need_schedule = true;
while (running_process || !inputQue.empty() || !readyQue.empty())
{
proc_ready(chip);
if (!readyQue.empty())
sort(readyQue.begin(), readyQue.end(), cmp_priority);
if (need_schedule && !readyQue.empty())
need_schedule = proc_start(chip);
print_all(chip);
chip += 1;
if (running_process)
{
running_process->remainTime -= 1;
if (running_process->remainTime == 0)
need_schedule = proc_finish(chip);
else
{
running_process->priority += 1;
if (!readyQue.empty() && readyQue[0].priority > running_process->priority)
need_schedule = context_switch();
else need_schedule = false;
}
}
}
print_all(chip);
}
int main()
{
printf("===================================================\n");
printf(" Simulation of operating system process scheduling \n");
printf("===================================================\n\n");
input_process();
//-1标志为打印所有进程的初始状态
//print_all(-1);
int policy = select_algorithm();
switch (policy)
{
case 1:
FCFS();
break;
case 2:
RR(5);
break;
case 3:
dynamic_priority();
break;
default:
FCFS();
break;
}
}
The contention scope refers to the scope in which threads compete for the use of physical CPUs
There are two possible contention scopes:
Different inter-process communication and synchronization techniques are required.
In multiprocessing systems, all processors share a memory.
There are three structures for multi-processor OS:
Separate Kernel Configuration: Each processor has its own I/O devices and file system. There is very little
interdependence among the processors. A process started on a processor runs to completion on that processor only.
Disadvantage: parallel execution is not possible. A single task cannot be divided into sub-tasks and distributed among several processors, thereby losing the advantage of computational speed-up
Master-Slave Configuration (Asymmetric Configuration): One processor as master and other processors in the system as slaves. The master processor runs the OS and processes while slave processors run the processes only. The process scheduling is performed by the master processor.
Advantage: The parallel processing is possible as a task can be broken down into sub-tasks and assigned to various processors.
Symmetric Configuration (SMP): Any processor can access any device and can handle any interrupts generated on it. Mutual exclusion must be enforced such that only one processor is allowed to execute the OS at one time. Mutual exclusion must be enforced such that only one processor is allowed to execute the OS at one time.
Processor affinity is the ability to direct a specific task, or process, to use a specified core.
The idea behind: if the process is directed to always use the same core it is possible that the process will run more efficiently because of the cache re-use. (If a process migrates from one CPU to another, the old instruction and address caches become invalid, and it will take time for caches on the new CPU to become ‘populated’)
Soft affinity: OSs try to keep a process running on the same processor but not guaranteeing it will do so
Hard affinity: allows a process to specify a subset of processors on which it may run.
When each processor has a separate ready queue, there can be an imbalance in the numbers of jobs in the queues.
Push migration: A system process periodically checks ready queues and moves (or push) processes to different queues, if need be.
Pull migration: If scheduler finds there is no process in ready queue so it raids another processor’s run queue and transfers a process onto its own queue so it will have something to run (pulls a waiting task from a busy processor).
A core executes one thread at a time
Memory stall: Single-core processor spends time waiting for the data to become available (slowing or stopping of a process)
Solution: to put multiple processor cores onto a single chip to run multiple kernel threads concurrently.
the physical processor is divided into two logical or virtual processors that are treated as if they are actually physical cores by the operating system (Simultaneous multithreading SMT). Hyper Threading allows multiple threads to run on each core of CPU
Techniques for multithreading:
A real-time system is one in which time plays an essential role. The RTOS schedules all tasks according to the deadline information and ensures that all deadlines are met.
Aperiodic tasks (random time) has irregular arrival times and either soft or hard deadlines.
Periodic tasks (repeated tasks), the requirement may be stated as “once per period T” or “exactly T units apart.”
Issues
The major challenge for an RTOS is to schedule the real-time tasks.
Two types of latencies may delay the processing (performance):
Static scheduling: A schedule is prepared before execution of the application begins.
Priority-based scheduling: The priority assigned to the tasks depends on how quickly a task has to respond to the event.
Dynamic scheduling: There is complete knowledge of tasks set, but new arrivals are not known. Therefore, the schedule changes over the time
The timing constraints are in the form of period
and deadline
. The period
is the amount of time between iterations of a regularly repeated task. Such repeated tasks are called periodic tasks. The deadline
is a constraint of the maximum time limit within which the operation must be complete.
The scheduling criteria in a real-time system:
The scheduling in real-time systems may be performed in the following ways: pre-emptively, non-preemptively, statically, and dynamically.
Takes a particular predetermined workload and defines the performance of each algorithm for that workload. What algorithm can provide the minimum average waiting time?
If we define a queue for the CPU and a queue for each I/O device, we can test the various scheduling algorithms using queueing theory.
Little’s formula: processes leaving queue must equal processes arriving, thus: n = λ × W n=\lambda\times W n=λ×W n = n= n= average queue length
W = W= W= average waiting time in queue
λ = \lambda= λ= average arrival rate into queue
We can use trace tapes. This is data collected from real processes on real machines and is fed into the simulation.
System consists of resources.
Resource types R 1 , R 2 , ⋯ , R m R_1, R_2, \cdots, R_m R1,R2,⋯,Rm. (CPU cycles, memory space, I/O devices)
Each resource type R i R_i Ri has W i W_i Wi instances.
Each process utilizes a resource as follows: request, use, release.
Deadlock can be defined as the permanent blocking of a set of processes that compete for system resources
Deadlock can arise if four conditions hold simultaneously:
Resource-Allocation Graph
A set of vertices V V V and a set of edges E E E, V V V is partitioned into two types:
and two types of E E E:
Ensure that the system will never enter a deadlock state
To deal with the deadlock, the following three approaches can be used:
adopting a policy that eliminates one of the conditions
we constrain resource requests to prevent at least one of the four conditions of deadlock.
Two approaches to deadlock avoidance:
A safe state is one in which there is at least one sequence of resource allocations to processes that does not result in a deadlock. If a system is in safe state, it implies no deadlocks. If a system is in unsafe state, it possibility of deadlock.
The avoidance approach requires the knowledge of:
A resource request is feasible, only if the total number of allocated resources of a resource type does not exceed the total number of that resource type in the system.
Two approaches to deadlock avoidance:
Single Instance of Resources: Where every resource type has a single instance of resource, the RAG can be used. Claim edge P i → R j P_i\rightarrow R_j Pi→Rj indicated that process P i P_i Pi may request resource R j R_j Rj, represented by a dashed line. After the cycle check, if it is confirmed that there will be no circular wait, the claim edge is converted to a request edge. Otherwise, it will be rejected. Request edge converted to an assignment edge when the resource is allocated to the process. When a resource is released by a process, assignment edge reconverts to a claim edge.
Multiple Instances of Resources: Banker’s Algorithm
Let n n n= number of processes, and m m m= number of resources types.
The banker’s algorithm has two parts:
Banker’s Algorithm 的 C++ 实现:
#include
#include
#include
using namespace std;
int P, R;
int maxs[10][10];
int allocation[10][10];
int need[10][10];
int available[10];
int request[10];
bool cmp(int m[],int n[])
{
for (int i=0; i<R; i++)
if (m[i] < n[i]) return false;
return true;
}
bool safety_test()
{
int flag = 0;
int finish[P];
int work[R];
copy(available, available+R, work);
memset(finish, 0, sizeof finish);
cout << "allocated sequence" << endl;
cout << " allocation need avilable" << endl;
for (int k=0; k<P; k++)
{
for (int i=0; i<P; i++)
{
if (finish[i] == 1) continue;
else
{
if (cmp(work, need[i]))
{
finish[i] = 1;
cout << endl << "processes" << i + 1 <<'\t';
flag = 1;
for (int j=0; j<R; j++)
{
printf(" %2d ", allocation[i][j]);
}
cout << " ";
for (int j=0; j<R; j++)
{
printf(" %2d ", need[i][j]);
}
cout << " ";
for (int j=0; j<R; j++)
{
work[j] += allocation[i][j];
printf(" %2d ", work[j]);
}
break;
}
}
if (flag == 1) break;
}
}
cout << endl;
for (int l=0; l<P; l++)
if (finish[l] == 0)
return false;
return true;
}
void resource_request(int n)
{
if (cmp(need[n], request))
{
if (cmp(available, request))
{
for (int j=0; j<R; j++)
{
need[n][j] -= request[j];
available[j] -= request[j];
allocation[n][j] += request[j];
}
if (safety_test())
{
cout << "The" << n << "th process's request is available." << endl;
}
else
{
cout << "The" << n << "th process's request is unavailable." << endl;
for (int j=0; j<R; j++)
{
need[n][j] += request[j];
available[j] += request[j];
allocation[n][j] -= request[j];
}
}
}
else
{
cout << "The" << n << "th process's request is unavailable." << endl;
}
}
else
{
// 此处应该抛出异常,由于不是重点所以略过。
cout << "ERROR!" << endl;
}
}
int main(void)
{
int n;
cout << "Please input the number of processes";
cin >> P;
cout << "Please input the number of the resources type";
cin >> R;
cout << "Please enter maxs matrix\n";
for (int i=0; i<P; i++)
for (int j=0; j<R; j++)
cin >> maxs[i][j];
cout<<"Please enter allocation matrix\n";
for (int i=0; i<P; i++)
for (int j=0; j<R; j++)
cin>>allocation[i][j];
cout << "Please enter needs matrix\n";
for (int i=0; i<P; i++)
for (int j=0; j<R; j++)
cin>>need[i][j];
cout<<"Please enter available vector\n";
for (int i=0; i<R; i++)
cin >> available[i];
if (safety_test())
{
cout << "There is a safe sequence, the initial state is safe.\n";
cout << "Please enter the number of the process that sent the request vector:";
cin >> n;
cout << "Please enter the request vector\n";
for (int i=0; i<R; i++)
{
cin >> request[i];
}
resource_request(--n);
}
else
{
cout << "There is no safe sequence, the initial state is not safe.\n";
}
return 0;
}
/*
4
3
3 2 2
6 1 3
3 1 4
4 2 2
1 0 0
5 1 1
2 1 1
0 0 2
2 2 2
1 0 2
1 0 3
4 2 0
1 1 2
2
1 0 1
*/
Ignore the problem and pretend that deadlocks never occur in the system (used by most operating systems, including UNIX)
Deadlock detection has two parts:
Detection of single instance of resource
Resource-Allocation Graph and Wait-for Graph:
Maintain wait-for graph:
Detection of mutiple instances of resources
The detection algorithm investigates every possible allocation sequence for the processes that remain to be completed. Algorithm requires an order of O ( m × n 2 ) O(m\times n^2) O(m×n2) operations to detect whether the system is in deadlocked state.
Detection-Algorithm Usage
If detection algorithm is invoked arbitrarily, there may be many cycles in the resource graph and so we would not be able to tell which of the many deadlocked processes “caused” the deadlock.
There are two options for breaking a deadlock:
Processes access memory using a virtual address (logical address), which generated by the CPU. The OS (hardware MMU) translates the virtual address into the physical RAM address. Each memory reference is passed through the MMU
assigns consecutive memory blocks to a process.
Fixed/Static Partitioning
Fixed partitions can be of equal or unequal sizes. Assign each process to their own partition.
Variable/Dynamic Partitioning
The operating system keeps a table indicating which parts of memory are available and which are occupied. List of free memory blocks (holes) to find a hole of a suitable size whenever a process needs to be loaded into memory.
Internal fragmentation
occurs in fixed size blocks, because the last allocated process is not completely filled.
Solution: can be reduced by using variable sized memory blocks rather than fixed sized.
External fragmentation
occurs with variable size segments, because some holes in memory will be too small to use.
Solutions:
assigns different blocks of memory in a nonconsecutive manner to a process.
The segments are logical divisions of a program, and they may be of different sizes. Each segment has a name and a length. A logical address space is a collection of segments.
Logical address consists of a two tuple:
Segment table maps two-dimensional logical address to one-dimensional physical address. Each table entry has:
Memory is divided into equal-size partitions called frames. Logical address is divided into blocks of same size as frames called pages of a process. All the pages of the process to be executed are loaded into any available frame in the memory.
Size of a page is between 512 bytes and 1GB
Logical Address generated by CPU is divided into:
Logical Address = Page number + Page offset
Physical Address = (Frame * Page size) + Offset
For given logical address space 2 m 2^m 2m and page size 2 n 2^n 2n, page number is m − n m-n m−n and page offset is n n n
Page table is a data structure and maps the page number referenced by the CPU to the frame number where that page is stored. The address of a page table is stored in the memory, is also stored in the PCB of the process.
segmentation 和 page 的区别:
Implementation of Page Table
Page table is kept in main memory. Page-table base register (PTBR) points to the page table. Page-table length register (PTLR) indicates size of the page table
Whenever a process is scheduled to be executed, the page table address from its PCB is loaded into PTBR, and the corresponding page table is accessed in the memory. When the current process is suspended or terminated, and another process is scheduled to execute, then the PTBR entry is replaced with the page table address of a new process (context switch). The two-memory access problem can be solved by the use of a special fast-lookup hardware cache called Translation Look-aside Buffer (TLB)
Total memory access time = Time to access page table + Time to access memory location
Paging Hardware With TLB
转译后备缓冲器,也被翻译为页表缓存、转址旁路缓存,为 CPU 的一种缓存,用于改进虚拟地址到物理地址的转译速度。TLB具有固定数目的空间槽,用于存放将虚拟地址映射至物理地址的标签页表条目。为典型的结合存储(content-addressable memory,CAM)。其搜索关键字为虚拟内存地址,其搜索结果为物理地址。如果请求的虚拟地址在 TLB 中存在,将给出一个非常快速的匹配结果,之后就可以使用得到的物理地址访问存储器。如果请求的虚拟地址不在 TLB 中,就会使用标签页表进行虚实地址转换,而标签页表的访问速度比 TLB 慢很多。有些系统允许标签页表被交换到次级存储器,那么虚实地址转换可能要花非常长的时间。
A translation look-aside buffer (TLB) is a memory cache that stores the recent translations of virtual memory to physical memory.
The percentage of times that the page number of interest is found in the TLB is called the hit ratio.
Let E E E = TLB lookup time, M M M = memory access time, A A A = hit ratio. Effective memory-access time (EAT) = estimation of the impact of the TLB on the execution speed of the computer.
E A T = A ( E + M ) + ( 1 − A ) ( E + 2 × M ) EAT=A(E+M)+(1-A)(E+2\times M) EAT=A(E+M)+(1−A)(E+2×M)
Memory Protection
Memory protection implemented by associating protection bit with each frame
Shared Pages
Motivation for page sharing:
Only one copy of the editor need be kept in physical memory. Each user’s page table maps onto the same physical copy of the editor. But data pages are mapped onto different frames.
Structure of the Large Page Table
Virtual memory (VM) is a method that manages the exceeded size of larger processes as compared to the available space in the memory.
Virtual memory - separation of user logical memory from physical memory.
The implementation of a VM system requires both hardware and software components. The software implementing the VM system is known as VM handler. The hardware support is the memory management unit built into the CPU.
The VM system realizes a huge memory only due to the hard disk. With the help of the hard disk, the VM system is able to manage larger-size processes or multiple processes in the memory. For this purpose, a separate space known as swap space is reserved in the disk. Swap space requires a lot of management so that the VM system woks smoothly.
The concept of loading only a part of the program (page) into memory for processing.
when the process begins to run, its pages are brought into memory only as they are needed, and if they’re never needed, they’re never loaded.
Lazy swapper: never swaps a page into memory unless page will be needed. Swapper that deals with pages is a pager.
How to recognize whether a page is present in the memory?
What happens if the process tries to access a page that is not in the memory?
When the page referenced is not present in the memory: page fault.
While translating the address through the page table notices that the page-table entry has an invalid bit. It causes a trap to the OS so that a page fault can be noticed.
What happens if there is no free frame?
The existing page in the memory needs to be paged-out.
Which page will be replaced? page-replacement algorithms.
Steps in Handling a Page Fault
No page fault: the effective access time = the memory access time.
Have page fault:
Let p p p be the probability of a page fault. The effective access time (EAT) is:
E A T = ( 1 − p ) × M e m o r y A c c e s s T i m e + p × P a g e F a u l t T i m e EAT=(1-p)\times Memory Access Time+p\times Page Fault Time EAT=(1−p)×MemoryAccessTime+p×PageFaultTime
Major components of the page-fault service time:
Only pages that are written need to be copied.
Process creation using the fork() system call may (initially) bypass the need for demand paging by using a technique similar to page sharing.
Copy-on-write = strategy that those pages that are never written need not be copied. Only the pages that are written need be copied.
The parent and child process to share the same pages of the memory initially. If any process either parent or child modifies the shared page, only then the page is copied.
When a page fault occurs during the execution of a process, a page needs to be paged into the memory from the disk.
The degree of multiprogramming increases result in over-allocating memory which implies no free frames on the free frame list, all memory is in use.
A good replacement algorithm achieves:
Basic Page Replacement
An algorithm is evaluated by running it on a particular string of memory references and computing the number of page faults. Record a trace of the pages accessed by a process.
Reference string: the sequence of pages being referenced.
When a page must be replaced, the oldest page is chosen.
Replace page that will not be used for longest period of time. It cannot be implemented, because there is no provision in the OS to know the future memory references. The idea is to predict future references based on the past data.
when a page fault occurs, throw out the page that has been unused for the longest time.
How to find out a page that has not been used for the longest time:
LRU needs special hardware and still slow.
Reference bit: will say whether the page has been referred in the last clock cycle or not. Reference bits are associated with each entry in the page table. The reference bit for a page is set by the hardware whenever that page is referenced (either a read or a write to any byte in the page).
keeps a circular list of pages in memory, with the iterator pointing to the last examined page frame in the list.
Iterator Scan:
Keep a counter of the number of references that have been made to each page.
Least Frequently Used (LFU) Algorithm replaces page with smallest count.
Most Frequently Used (MFU) Algorithm is based on the argument that the page with the smallest count was probably just brought in and has yet to be used.
The two algorithms commonly used to allocate frames to a process:
Thrashing: A process is busy swapping pages in and out.
If a process does not have “enough” pages, the page-fault rate is very high. This leads to:
Types of Secondary Storages:
Moving-head Disk Mechanism
Disk address can be specified by the cylinder, head and sector numbers, or CHS addressing.
Disk speed
Disk is addressed as a one-dimension array of logical sectors. Disk controller maps logical sector to physical sector identified by track, surface and sector.
Computer systems can access disk storage in two ways:
Goal: minimize the positioning time. Scheduling is performed by both O.S. and disk itself
works well with light loads; but as soon as the load grows, service time becomes unacceptably long.
quite popular and intuitively appealing. It works well with moderate loads but has the problem of localization under heavy loads.
works well with light to moderate loads and eliminates the problem of indefinite postponement. SCAN is similar to SSTF in throughput and mean service times.
works well with moderate to heavy loads and has a verysmall variance in service times.
Low-level formatting, or physical formatting — create sectors on a blank platter. Each sector can hold header information, plus data, plus error correction code (ECC). Usually, 512 bytes of data but can be selectable
Partition organize disk in one or more groups of cylinders
Logical formatting write file system data structures
Boot block initializes system: The bootstrap is stored in ROM. Bootstrap loader program stored in boot blocks of boot partition.
Swap-space: Virtual memory uses disk space as an extension of main memory
Configure Swap-space:
RAID: Redundant Arrays of Independent Disks.
RAID is a system of data storage that uses multiple hard disk drives to store data. RAID is a set of physical drives viewed by the operating system as a single logical drive.
RAID controller is used for controlling a RAID array. It may be hardware- or software-based.
There are three main techniques used in RAID:
There are several different storage methods, named levels.
Level 0 does not provide redundancy. It treats multiple disks as a single partition. Files are Striped across disks, no redundant info.
High read throughput but any disk failure results in data loss.
bit-interleaved parity organization is a modification of Level 2 and requires only a single redundant disk, no matter how large the disk array.
single parity bit can be used for error correction / detection for each strip, and it is stored in the dedicated parity disk.
Suppose, strip X = {1010}, the parity bit is 0 as there are even number of 1s.
Suppose X = {1110}, the parity bit here is 1 as there are odd number of 1s.
block-interleaved distributed parity is a modification of Level 4.
the parity bits are not stored in a single disk, distributes the parity strips across the disks.
What are file systems
Everything is stored as files in a computer system. The files can be data files or application files. A file is a named, linear region of bytes that can grow and shrink. The operating system performs this management with the help of a program called File System.
Different operating systems use different file systems:
The user level of the file system (more visible)
Attributes of a File
A file is a named, linear region of bytes that can grow and shrink.
Basic File Operations
File systems break files down into two logical categories:
Open File Table
Since the open operation fetches the attributes of the file to be opened, the OS uses a data structure known as open file table (OFT), to keep the information of an opened file.
When it is used, the information must be accessed and read into computer memory.
The information in the file can be accessed in several ways:
Disk Structure - Storage Structure
A disk can be used in its entirety for a file system. A disk can be broken up into multiple partitions, slices, or mini-disks, each can have its own filesystem.
Disk/partition is partitioned into Blocks or Sectors. Modern disks have 512-byte or more sectors. File Systems usually work in block sizes of 4 KB
Directory - Operations Performed on Directory
The directories are used to maintain the structure of a file system.
Directories serve two purposes:
Operations:
Schemes of logical structure of a directory
Protection mechanisms provide controlled access by limiting the types of file access that can be made.
File owner/creator should be able to control:
Mounting = attaching portions of the file system into a directory structure.
In Windows, the devices and/or partition can be accessed by opening My Computer on the desktop.
Access-Control List and Groups
general scheme to implement identity dependent access is to associate with each file and directory an access-control list (ACL) specifying usernames and the types of access allowed for each user.
Mode of access: read, write, execute (R, W, X)
The classifications:
Sharing must be done through a protection scheme
May use networking to allow file system access between systems
Client-server model allows clients to mount remote file systems from servers
Distributed Information Systems implement unified access to information needed for remote computing (LDAP, DNS, NIS, Active Directory).
The OS level of the file system.
File system needs to maintain on-disk or in-memory structures
On disk, the file system may contain information about how to boot an operating system stored there, the total number of blocks, the number and location of free blocks, the directory structure, and individual files.
File mapping through FCB
The file system uses the logical position in a file stored by the FCB to map it to a physical location on the disk. The FCB contains a list of blocks of a file and their corresponding disk block addresses. To retrieve the data at some position in a file, the file system first translates the logical position to a physical location in the disk.
The in-memory information is used for both file-system management and performance improvement via caching.
A directory is a container which contains file and folder.
We can store the list of files as:
Allocation methods
There are three major allocation strategies of storing files on disks:
Contiguous Allocation: Each file occupies a set of contiguous blocks on the disk.
linked: each file is a linked list of disk blocks. Only efficient for sequential access files, random access requires starting at the beginning of the list for each new location access.
indexed: Each file has its own index block(s) of pointers to its data blocks. Brings all pointers together into the index block.
Unix Inode
Unix uses an indexed allocation structure. An inode (indexed node) stores both the attributes (infos) and the pointers to disk blocks. Typically, an inode contains 15 pointers as follows:
Free-Space Management
Disk management maintains free-space list to track available blocks / free space.
I/O management is a major component of operating system design and operation
The IO devices are classified:
Network device: to send or receive data on a network.
Common concepts: signals from IO devices interface with computer
Each controller has registers that are used for communicating with the CPU. There are data buffer that the operating system can read and write. Each IO port (device) is identified by a unique port address.
Each IO port consists of 4 registers (1-4 bytes in size):
how to address a device:
Three techniques by which an IO operation can be performed on a device:
Polling: The data transfer is initiated by the instructions written in a computer program. CPU executes a busy-wait loop periodically checking status of the device to see if it is time for the next I/O operation (tests the channel status bit). CPU stays in a loop until the I/O device indicates that it is ready for data transfer. Polling can be very fast and efficient, if both the device and the controller are fast and if there is significant data to transfer. It keeps the processor busy needlessly and leads to wastage of the CPU cycles
Interrupt-driven IO: In pooling the processor time is wasted ⇒ \Rightarrow ⇒ a hardware mechanism: interrupt. the CPU has an interrupt-request line that is sensed after every instruction. Interrupts allow devices to notify the CPU when they have data to transfer or when an operation is complete. The CPU transfers control to the interrupt handler. Most CPUs have two interrupt-request lines:
How does the processor know when the I/O is complete?
Through an interrupt mechanism. when the operation is complete, the device controller generates an interrupt to the processor. NB: the processor checks for the interrupt after every instruction cycle. after detecting an interrupt, the processor will perform a context switch, by executing the appropriate Interrupt Service Routine. Interrupt handler receives interrupts the processor then performs the data transfer for the I/O operation.
Interrupt Driven IO Cycle
The basic protocol to interact with an I/O device
Wait for drive to be ready. Read Status Register until drive is not busy and READY. Write parameters to control registers. Write the sector count, logical block address (LBA) of the sectors to be accessed, and drive number. Start the IO. by issuing read/write to Control register. Data transfer (for writes): Wait until drive status is READY and DRQ (drive request for data); write data to data port. Handle interrupts. In the simplest case, handle an interrupt for each sector transferred; more complex approaches allow one final interrupt when the entire transfer is complete. Error handling. After each operation, read the status register. If the ERROR bit is on, read the error register for details.
Direct Memory Access: when the data are large, interrupt driven IO is not efficient. Instead of reading one character at a time through the processor, a block of characters is read at a time. Bypasses CPU to transfer data directly between IO device and memory. DMA hardware generates an interrupt when the IO transaction is complete. Requires DMA controller. Version that is aware of virtual addresses can be even more efficient: Direct Virtual Memory Access DVMA.
To read or write a block, the processor sends the command to the DMA controller. The processor passes the following information to the DMA controller:
User application access to a wide variety of different devices. Device-driver layer hides differences among I/O controllers from kernel
Devices vary in many dimensions:
This part is provided in the kernel space. The user interacts with this layer to access any device.
There are different functions:
At the lowest level, a piece of software in the OS must know in detail how a device works. We call this piece of software a device driver, and any specifics of device interaction are encapsulated within.
The functions of a device driver are to:
The device driver communicates with the device controllers, and then the device, with the help of the interrupt-handling mechanism.
The Interrupt Service Routine (ISR) is executed in order to handle a specific interrupt for an IO operation.
a full-duplex communication channel between a user-level process and a device in Unix System V and beyond.
A STREAM consists of:
Each module contains a read queue and a write queue. Message passing is used to communicate between queues. Flow control can be optionally supported. Without flow control, data is passed along as soon as it is ready.
Protection refers to a mechanism which controls the access of programs, processes, or users to the resources defined by a computer system.
Goals of Protection
Principle of least privilege
The principle of least privilege dictates that programs, users, and systems be given just enough privileges to perform their tasks.
Can be static (during life of system, during life of process), or dynamic (changed by process as needed) – domain switching, privilege escalation
View protection as a matrix (access matrix)
Role-based access control (RBAC) is a security feature for controlling user access to tasks that would normally be restricted to the root user.
RBAC, assigns first the roles and then all the permissions are assigned.
Security is the practice of the confidentiality, integrity, and availability of data
Security Violation Categories
Security Violation Methods
Security Measure Levels
To protect a system, we must take security measures at four levels:
Cryptography is a technique to hide the message using encryption.
Encryption
Encryption is a process of encoding a message so that its meaning cannot be easily understood by unauthorized people
Symmetric Encryption
Same key used to encrypt and decrypt.
Data Encryption Standard (DES) was most commonly used symmetric block-encryption algorithm. Triple-DES considered more secure.
Advanced Encryption Standard (AES)
Rivest Cipher RC4 is most common symmetric stream cipher, but known to have vulnerabilities
Asymmetric Encryption
Public-key encryption based on each user having two keys:
Most common is RSA (RSA = Ron Rivest, Adi Shamir and Leonard Adleman) based on prime numbers
Digital Certificates
A digital certificate is a mechanism that allows users to verify the authenticity of a key / document.
Key Distribution Management
Keys in Symmetric encryption is a major problem. One option is to send them Out-of-band, say via paper or a confidential conversation or One-time pad
Keys in Asymmetric encryption, the public keys are not confidential. The key-ring can be easily stored and managed (key-ring is simply a file with keys in it.).
Even asymmetric key distribution needs care, because of man-in-the-middle attack
When a user logs into a computer, the OS needs to determine the identity of the user.
The user authentication has two steps:
There are two main authentication algorithms:
Common forms of user authentication
The major methods, tools, and techniques that can be used to improve security:
Security Policy
Vulnerability Assessment: Periodically examine the system to detect vulnerabilities.
Intrusion Detection
Virus Protection
Auditing, Accounting, and Logging
Virtualization is technology that allows to create multiple simulated environments or dedicated resources from a single, physical hardware system.
Software called a hypervisor connects directly to that hardware and allows to split a system into separate, distinct, and secure environments known as virtual machines (VMs).
Virtual machine manager (VMM) or hypervisor – creates and runs virtual machines by providing interface that is identical to the host (except in the case of paravirtualization)
Virtual machine implementations involve several components
the hypervisor provides a layer between the hardware (the physical host machine) and the Virtual Machines (guest machines)
Implementation of VMMs
Types of virtual machine manager VMMs:
the ability to share the same hardware yet run several different execution different operating systems concurrently.
Host system protected from VMs, VMs protected from each other:
a perfect for operating-system research and development
virtualized workstation allows for rapid porting and testing of programs in varying environments
Consolidation involves taking two or more separate systems and running them in virtual machines on one system
can improve resource utilization and resource management
Live migration: move a running VM from one host to another
Distributed system is a loosely-coupled architecture, wherein processors are inter-connected by a communication network. The processors and their respective resources for a specific processor in a distributed system are remote, while its own resources are considered as local.
Processors variously called nodes, computers, machines, hosts.
Reasons for Distributed Systems
Types of Network-oriented OS