Name three techniques that may be employed in the operating system to increase CPU utilization.
CPU Utilization: percentage of time that the CPU is busy
- The OS uses multiprogramming, or concurrency,(one process on the CPU running and one or more doing I/O) to increase system utilization and throughput by overlapping I/O and CPU activities.
- Set Non-preemptive process to reduce the context switch time
- Non-preemptive schedule : FCFS
Name and describe the three interfaces that are part of the operating system. Be certain to include the purpose of each and how it relates to the OS and the other interfaces.
Abstract Machine Interface (AMI)
• between OS and apps: API + memory access model +
legally executable instructions
– Application Programming Interface (API)
• function calls provided to apps
– Hardware Abstraction Layer (HAL)
• abstracts hardware internally to the OS
Does the implementation of the write() system call use any of the interfaces you named above? If so, which ones? Defend your answer.
Yes. use HAL, AMI is the highest layer. write() is in API, it is above HAL.
How does dual-mode execution provide protection in the system?
User mode: access is restricted
– Kernel mode: access is unrestricted
dual-mode
Supported by the hardware
• Mode is indicated by a bit in the process status register
Name two ways system calls and procedure calls are different.
- procedure calls refer to the same concept which is calling a block of code in user space. system call refers to calling an operating system service running in privileged kernel space.
- procedure calls is coded by user, while the system calls are coded by the designer.
Circle any and all statements that cause a mode switch.
[A] A call to read() from a user’s procedure call.
[B] A user application dereferences a NULL pointer.
[C] An interrupt occurs while a signal is being delivered.
[D] A system call detects bad user input and terminates the process.
[E] A user program calls its own function foo().
[F] A shell calls fork()
A B C D F
How does receiving a signal affect a process? Be sure to consider both the case where a handler is installed and the case where one is not.
Terminating a process: kill()
• A parent can terminate a child using kill()
– kill() is also used for interprocess
communication
• This system call:
– Sends a signal to a specified process (identified by
its PID)
• SIGHUP, SIGKILL, SIGCHLD, SIGUSR1, SIGUSR2
– The receiving process can define signal handlers to
handle signals in a particular way
– If a handler for that signal does not exist, the
default action is taken
In Project 0, why did we use sigsuspend()?
sigsuspend用于在接收到某个信号之前,临时用mask替换进程的信号掩码,并暂停进程执行,直到收到信号为止。
sigsuspend() temporarily replaces the signal mask of the calling thread with the mask given by mask and then suspends the thread until delivery of a signal whose action is to invoke a signal handler or to terminate a process.
Why is sigsuspend() preferable to pause()?
Sometimes, pause() will not change the signal mask, it would block forever.
sigsuspend() has the same function but more powerful.
Draw the process life cycle
A : running to ready, this process is ok, but wait other processes
Consider the following pseudocode, which you may assume compiles and runs:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int c = 7;
int main(){
pid_t pid = fork();
c++;
if(pid == -1)
exit(-1);
else if(pid == 0){
c += 2;
printf("I am the child, c is %d\n", c);
}
else {
c += 4;
printf("I am the parent, c is %d\n", c);
}
}
, c is 12
I am the child, c is 10
Is any other output possible? Defend your answer.
I am the child, c is 10
I am the parent, c is 12
- no output, just exit, fork failed.
Consider the following code, which creates kernel threads:
In class, we studied the Multilevel Feedback Queue Scheduler.
What is the overall goal of the MLFQ scheduler?
Firstly, it is more flexible than multilevel queue scheduling.
To optimize turnaround time algorithms like SJF are needed which require the running time of processes to schedule them. But the running time of the process is not known in advance. MFQS runs a process for a time quantum and then it can change its priority(if it is a long process). Thus it learns from past behavior of the process and then predicts its future behavior. This way it tries to run a shorter process first thus optimizing turnaround time.
MFQS also reduces the response time.
MLFQS is an approximation of what other scheduler we studied
Approximating SJF:optimize turnaround time algorithms
Turnaround time: length of time to run a process from initialization to termination, including all the waiting time
Response time: time between issuing a command and getting a result
Synchronization Short Answer
In class, we studied semaphores and monitors.
- Both semaphores and monitors are used to solve the critical section problem (as they allow processes to access the shared resources in mutual exclusion) and to achieve process synchronization in the multiprocessing environment.
Monitor:
A Monitor type high-level synchronization construct. It is an abstract data type. The Monitor type contains shared variables and the set of procedures that operate on the shared variable.
When any process wishes to access the shared variables in the monitor, it needs to access it through the procedures. These processes line up in a queue and are only provided access when the previous process release the shared variables. Only one process can be active in a monitor at a time. Monitor has condition variables.
monitor {
//shared variable declarations
data variables;
Procedure P1() { ... }
Procedure P2() { ... }
.
.
.
Procedure Pn() { ... }
}
A Semaphore is a lower-level object. A semaphore is a non-negative integer variable. The value of Semaphore indicates the number of shared resources available in the system. The value of semaphore can be modified only by two functions, namely wait() and signal() operations (apart from the initialization).
When any process accesses the shared resources, it performs the wait() operation on the semaphore and when the process releases the shared resources, it performs the signal() operation on the semaphore. Semaphore does not have condition variables. When a process is modifying the value of the semaphore, no other process can simultaneously modify the value of the semaphore.
The Semaphore is further divided into 2 categories:
Binary semaphore
Counting semaphore
// Wait Operation
wait(Semaphore S) {
while (S<=0);
S--;
}
// Signal Operation
signal(Semaphore S) {
S++;
}
Advantages of Monitors:
Monitors are easy to implement than semaphores.
Mutual exclusion in monitors is automatic while in semaphores, mutual exclusion needs to be implemented explicitly.
Monitors can overcome the timing errors that occur while using semaphores.
Shared variables are global to all processes in the monitor while shared variables are hidden in semaphores.
Advantages of Semaphores:
Semaphores are machine independent (because they are implemented in the kernel services).
Semaphores permit more than one thread to access the critical section, unlike monitors.
In semaphores there is no spinning, hence no waste of resources due to no busy waiting.
(a) In each of the following design situations, which would you choose?
i. [1pt] You are programming an application for multiple users to access anddisplay data.
semphore.
Semaphores permit more than one thread to access the critical section, unlike monitors.
ii. [1pt] You are coordinating events between two threads in the kernel.
semphore.
Semaphores are machine independent (because they are implemented in the kernel services).
(b) [3pts] How many locks does a monitor have? Why?
There is only one lock per monitor; by convention this lock is always called “lock”.
© [4pts] Does a monitor prevent against deadlock? Defend your answer.
Yes. 不满足第4个条件,形成锁的循环链。
Concurrency and Advanced Synchronization
(a) [4pts] Name two common concurrency bugs and explain how each might occur.
Two types of bugs – Deadlocks: threads cannot execute any further
and wait for each other – Non-deadlock bugs: non deadlock but incorrect
results when threads execute
Non deadlock and deadlock bugs.
Of the non-deadlock bugs, the main types are:
Atomicity Violation Bugs : atomicity assumptions madeby programmer are violated during executionof concurrent threads。fix : Always use locks when accessing shared data
Order Violation Bugs:desired order of memory accesses is flipped during concurrent
execution – Fix: condition variables
死锁的四个必要条件 :
- Mutual exclusion
- Hold-and-wait: They hold the lock while waiting for other resources
- No preemption: Resources cannot be forcible removed from threads that hold them.
- Circular wait: There is a circular chain of threads s.t. each holds one or more resources that are being requested by the next thread in the chain.
fix : destory one conditions.
(b) [4pts] For each bug you mentioned in 6a, how do you structure your code so that
the bug does not occur?
© [3pts] When using fine-grained locking, what technique will allow you to guarantee against deadlock? Defend your answer.
仅在必要时锁定并在不必要时尽快解除锁定来实现最大并行性(这种方法称作“细粒度锁定 (fine-grained locking)”)?还是要长期持有锁定,以使使用和释放锁的开销降到最低程度(这种方法称作“粗粒度锁定 (coarse-grained locking)”)?
信号量和监视器
两道题:
Synchronization (Coding)
”To the left, to the left, everything you own in a box to the left...”
While out shopping with her girlfriends one day, Beyonc´e discovers that her boyfriend has been
cheating on her. Beyonc´e heads home to throw her cheating boyfriend out.
When Beyonc´e arrives home, she tells her (now) ex to pack all of his things into boxes (on the left,
naturally) and waits for him to do so. The waiting is longer than she had hoped, though, because
her ex first has to acquire boxes (he needs two! ) before he can pack them. Fortunately, he finds a
pile of seven in the alleyway. When he is finished packing, Beyonc´e calls him a cab.
Once the cab has been summoned, Beyonc´e storms o↵ to do Beyonc´e things and her ex waits for
the cab. When the cab arrives he loads his things into the cab and then leaves with the driver.
Model this situation using both semaphores and monitors. Write three functions:
void beyonce()
//function executed by Beyonce, who arrives home from
//shopping and tells her boyfriend to pack his things.
//Once he is finished packing, she calls him a cab and
//then storms off.
void ex()
//function executed by boyfriend, who waits for
//Beyonce to arrive home, acquires boxes, packs,
//waits for the cab, loads in his things, and rides away
void cab_driver()
//function executed by cab drivers, who wait for someone
//to need a cab, drive to the correct location, wait
//for the cab to be loaded, and then drive to the
//destination
1. [8pts] Solve the problem using semaphores.
2. [12pts] Solve the problem using monitors.
Be certain to follow coding conventions discussed in class and to write your solutions so that they
can be run by many instances of Beyonc´e, Beyonc´e boyfriends, and cab drivers at the same time.
You may indicate any non-synchronization or mutual exclusion activities using the angle bracket
convention we used in class (e.g., <pack> or <drive>). You may assume the box pile is periodically
refreshed.
Clearly indicate your solutions to parts (a) and (b).
It’s a beautiful Fall day, and you notice that the UTCS students in the lab with you are
feeling restless as they try to solve is
interior(before) || is
tail(before) bugs.
As you notice the lab getting emptier, you follow the next student to leave. That’s
when you discover that, one by one, your fellow students have been slipping away to a
nearby field for games of pickup soccer—maybe fresh air and exercise will help them
solve those bugs!
Out at the field, everything appears to be running smoothly—the coaches for each
team are responsible for recruiting players to their teams, and, once the team is ready,
the coach signals the referee that they are ready to play and then waits for the game
to start. The players are arriving at the field ready to play, and notifying the coaches
that they have arrived. After connecting with a coach, they wait for the game to start.
The referees are retrieving one of eight game balls and then waiting for two teams to
be ready. Once two teams are ready, the referee signals for the game to start—and the
game starts, the players play, the coaches coach, and the referees referee.
Upon closer inspection, though, you notice that the referees don’t seem to quite un-
derstand when a game should end, and they are instead allowing the game to continue
for much too long. At some point in every game, the players and coaches(! ) collapse
from exhaustion and then just wait for the game to finish. Once the referee finally
signals the end of the game, the players and coaches crawl away, grateful to return to
harmless Pintos bugs.
The whole situation seems at once amazing and surreal—and then you realize that it
is really just a synchronization problem, and you can model each person’s actions in
code. In fact, by considering the three roles on the field, you realize you can model
everyone’s actions in three functions:
void players()
//function executed by players, who let the coaches
//know when they are ready, wait for the game to start,
//play hard, collapse when they are exhausted, and then
//crawl away once the game ends
void coaches()
//function where the coach waits for four players to
//be ready, notifies the referee when the team is
//gathered, waits for the start of the game, coaches
//the game, collapses from exhaustion, and then crawls
//away at the end of the game
void referee()
//function executed by referees, where the referee
//acquires a ball, waits for two teams to be ready,
//notifies the coaches and players of the start of
//the game, and then signals the end of the game. Once
//the game ends, the referee returns the ball
(a) [8pts] Solve the problem using semaphores.
(b) [12pts] Solve the problem using monitors.
做题步骤
- 题干
- 画图,捕捉动词
- 写伪码
- Criteria
Criteria
A Semaphore is a lower-level object. A semaphore is a non-negative integer variable. The value of Semaphore indicates the number of shared resources available in the system. The value of semaphore can be modified only by two functions, namely wait() and signal() operations (apart from the initialization).
6. 信号量是一个整数,对它的操作是原子的。atomic.即一个进程对信号量的更改不会影响其他信号量的操作。
7. 可以有两种操作,wait() signal().库函数有相关定义,直接用即可,操作系统实现原子性。
8. 有增一定有减
9. 提炼动词
10.
11.
12.
1
2
监视器
- 一种高级的抽象出来的数据结构,用于解决进程同步。
- 这个数据结构包含所有的共享变量,以及所有对该变量应该有的操作。
- 对共享变量操作,就需要关于这个变量的锁,二值,通过wait和signal判断是否能够对共享变量操作。
- 只有一个锁,对所有的共享变量起作用。同一时刻,只有一个procedure能够运行。
- procedure 只能访问本地的变量,包括共享变量和条件变量
- 共享变量和条件变量只能被monitor内部的procedure操作
区别:
8. 进程开始结尾的lock
9. 和信号量对应位置的up以及down对应起来操作。先wait后signal
涉及到条件变量的使用:
在什么情况下,要wait? 想要减的时候,不能减成负数。所以要wait,放到等待队列。 加的话可以直接加,保证不会有其他进程访问这个共享变量。