2017a Spring cs3733 Final Solution
2017a Spring cs3733 Final Solution
2017a Spring cs3733 Final Solution
____________________________KEY______________________________________
CS 3733.001 -- Operating system
Spring 2017 -- Final -- May 8, 2017 @9:45am
You have 120 min. Good Luck!
This is a closed book/note examination. But You can use the reference card(s) given to you.
This exam has 8 questions in 11 pages. Please read each question carefully and answer all the questions,
which have 100 points in total. Feel free to ask questions if you have any doubts about questions.
Partial credit will be given, so do not leave questions blank.
______________________________________________________________________________________________________________
You can also get 2pt bonus credit if you complete the following survey questions and the boldfaced two
columns of the grading table below. Please do this after answering the questions in the exam. Thanks!
Survey Questions (circle one):
I took Data Structures from Korkmaz Clark Sherette Tosun other
I took System Prog. from Lama Maynard other
I took Computer Org. from Tian Muzahid Clark Yu other
I took Application Prog. from Bylander Zhang Quarles Robinson other
Total 100+2
1
1. [20 points] Answer the following questions with short explanations. You can also draw figures to
better explain your reasoning if needed.
a. [2pt] Explain the differences between System calls and Library function calls in C?
[web] System calls and library calls are similar in that they are provided to application by
the environment. The difference between the two is that system calls are implemented in
kernel, whereas library calls are implemented in user space. ... The underlying hardware
provides a gate for user applications to enter kernel mode
b. [1pt] What is the purpose of using static before a variable name inside a C function?
[web] A static variable inside a function keeps its value between invocations.
A static global variable or a function is "seen" only in the file it's declared in
[web] Preemptive Scheduling means once a process started its execution, the currently
running process can be paused for a short period of time to handle some other process of
higher priority, it means we can preempt the control of CPU from one process to another if
required.
A computer system implementing this supports multi-tasking as it gives the user
impression that the user can work on multiple processes.
It is practical because if some process of higher priority is encountered then the current
process can be paused to handle that process.
Examples:- SRTF, Priority, Round Robin, etc.
Non-Preemptive Scheduling means once a process starts its execution or the CPU is
processing a specific process it cannot be halted or in other words we cannot preempt (take
control) the CPU to some other process.
A computer system implementing this cannot support the execution of process in a
multi task fashion. It executes all the processes in a sequential manner.
It is not practical as all processes are not of same priority and are not always known to the
system in advance.
Examples:- FCFS, SJF, Priority, etc.
d. [1pt] What is the difference between binary file and text file?
[web] The two file types may look the same on the surface, but their internal structures are
different. While both binary and text files contain data stored as a series of (bits (binary
values of 1s and 0s), the bits in text files represent characters, while the bits in binary files
represent custom data.
when we open a binary file in a text editor, each byte will be treated as a character. But
since many of them would be (non-printable) characters, we will mostly see junk.
2
e. [2pt] What is a Named Pipe (FIFO)? What advantages it has over regular (unnamed) pipe?
[web] Named pipes (FIFOs) are persistent objects represented by nodes in the file system.
A named pipe provides many-to-many, two-way communication between one or more
processes that are not necessarily related and do not need to exist at the same time. The file
name of the pipe serves as an address or contract between the processes for
communication. If only one process writes to a named pipe and one other process reads
from the named pipe, then the named pipe behaves in the same way as an unnamed pipe
between the two related processes.
So the short answer is that you need a named pipe for communication between unrelated
processes that might not exist at the same time.
+ you don't have to start the reading/writing processes at the same time
+ you can have multiple readers/writers which do not need common ancestry
+ as a file you can control ownership and permissions
f. [2pt] What do Dynamic loading and Dynamic linking means? Why do we need them?
[web] Dynamic loading means loading the library (or any other binary for that matter) into
the memory during load or run-time.
Dynamic loading can be imagined to be similar to plugins , that is an exe can actually
execute before the dynamic loading happens(The dynamic loading for example can be
created using LoadLibrary call in C or C++)
Dynamic linking refers to the linking that is done during load or run-time and not when
the exe is created.
In case of dynamic linking the linker while creating the exe does minimal work.For the
dynamic linker to work it actually has to load the libraries too.Hence it's also called linking
loader.
g. [2pt] What does locality means? How does it impact the performance of demand paging?
most programs spend most of their time using a small fraction of their code and data. so if
the locality is high the pages that are in the memory will be enough to execute the program
without page faults for a long time, if locality is not good we will keep handling page
faults, which is an time consuming job.
[wiki] A LWP runs in user space on top of a single kernel thread and shares its address
space and system resources with other LWPs within the same process. Multiple user level
threads, managed by a thread library, can be placed on top of one or many LWPs - allowing
multitasking to be done at the user level, which can have some performance benefits.
In some operating systems there is no separate LWP layer between kernel threads and user
threads. This means that user threads are implemented directly on top of kernel threads. In
those contexts, the term "light-weight process" typically refers to kernel threads and the
term "threads" can refer to user threads
3
i. [2pt] Describe the following requirements for critical section (CS) solutions:
Mutual Exclusion:
Progress:
Bounded Waiting:
[web]Mutual Exclusion: Only one process can be in the critical section at a time --
otherwise what critical section?.
Progress: No process is forced to wait for an available resource -- otherwise very wasteful.
Bounded Waiting: No process can wait forever for a resource -- otherwise an easy
solution: no one gets in.
j. [2pt] Give the similarities and differences between signals and interrupts?
[quora] Signals and interrupts are asynchronous event --- meaning, they can arrive at any
point in your program.
Interrupts are hardware-specific constructs. The kernel handles and deals with these,
either as part of normal I/O from/to devices, executing syscalls (as software interrupts
invoked by normal processes) or special conditions (page faults, divide by zero and so on).
Exceptions are synchronous --- they happen when and because your program made them
happen. Sometimes "making them happen" is inadvertent (some things that start as signals
--- e.g. memory-reference errors --- can get turned into exceptions by the low-level signal
handler in the runtime).
Exceptions are entirely userspace constructs and mostly tied to a language implementation.
They are alternative means of flow control, usually employed to handle error conditions.
k. [1pt] A protocol is an agreement between two end points that want to communicate. What
are the three main things that we need to specify when designing a networking protocol?
Protocols specify message format, in which order to send/receive these messages, and
what actions to take upon sending/receiving when certain messages.
4
2. [10 points] Unix I/O and file operations - Special Files
a. [5 points] Suppose that the file “tmpdata.txt” contains “abcdefghijk”. Suppose
the following code is executed correctly without generating any errors.
1: int fd;
2: char buf[6] = “12345”;
3: fd = open(“tmpdata.txt”, O_RDONLY);
4: fork( );
5: read(fd, buf, 2);
6: read(fd, buf+2, 2);
7: printf(“%d: %s ”, (long)getpid(), buf);
i). [3pt] Explain if the following two outputs are possible or not? Why/why not? Suppose
parent's pid is 7 while child's pid is 8.
7:b2ef5 Yes, possible, since system file table entry and thus
8:a2cd5 offset is shared, each reads 1 or 2 char and advance the offset.
accordingly the other reads the next one.
7:abcd5 Not possible, since system file table entry and thus
8:a2b45 offset is shared, they need to read different char!
ii). [2pt] Suppose the lines 3 and 4 are exchanged? Explain why (or why not) the above
outputs are possible in this case.
first one is not possible but the second one is possible this
time because they open the file after fork and each process
has its own offset.
b. [5 points] Suppose you are given the inode structure as shown below. Assume that our
inode structure has 10 direct pointers, and the data Block size is 8K bytes and pointers are 4
bytes. Write a function int num_of_data_block_di(struct inode *myinode); which
counts the number of data blocks under double indirect link. Note that double indirect
level might be partially filled with data blocks! So if there is no more data block or level,
the corresponding pointer will contain NULL. Please take that into account! If needed, you
can assume that the standard libraries are included here.
int num_of_data_block_di(struct inode *myinode){
int i, j, k;
int count=0;
int num_blk_ptr = _______ 8 * 1024 / 4;
if (myinode->di)
db for(i=0; i < num_blk_ptr; i++)
if (myinode->di[i])
for(j=0; j < num_blk_ptr; j++)
if (myinode->di[i][j])
count++
si
di return count;
}
ti
5
3. [15 points] Memory Management
a. [5 points] Suppose that the virtual address space is 16 Mbytes, the physical memory is 128
Kbytes, and the page/frame size is 2 Kbytes. Show how to determine the following bits:
i. [1pt] Number of bits for virtual address = ____24 bits_______
ii. [1pt] Number of bits for physical address = ____17 bits _______
iii. [1pt] Number of bits for offset (d) = ____11 bits______
iv. [1pt] Number of bits for page number (p) =____13 bits_______
v. [1pt] Number of bits for frame number (f) =____6 bits______
b. [5 points] Suppose we use TLB in the above system with the following page table and
TLB table entries. For memory address translation, suppose the TLB access time is 6 ns
and the memory access time is 20 ns while the disk access time is 10 ms.
initial page table TLB
Index Valid frame
0 0 6 Page Frame
1 1 5 2 7
2 1 7 3 4
3 1 4 1 5
4 0 3 6 9
5 1 8
6 1 9
… …
For the logical/virtual address given in binary below, find the corresponding page number
and frame number while estimating the time to access the actual data/instruction in the
physical memory (suppose we always first check TLB and then check page table if the
page number is not in TLB). Also give the corresponding physical memory address.
The given logical/virtual address is 0000 0000 0010 1001 1010 0010
[1pt] Page # = _______0 0000 0000 0101 = 5____________
[2pt] Access time = _____6ns tlb +20ns page table + 20ns access_ = 46 ns
[1pt] Frame # = _____________1000 = 8_______________
[1pt] Physical Address = ___________0 0100 0001 1010 0010________
c. [5 points] Suppose you are writing a C program to translate a given logical/virtual address
(LA) to a physical address (PA). You need to first find the page number (p) and offset
number (d). Then get frame number (f) from page table and determine PS. For the above
system (3.a), what statements would you use to find p, d and PA? Suppose LA is given.
unsigned int pn,dn,fn,PA,LA=0x9F28A3; // 1001 1111 0010 1000 1010
0011
dn = LA & 0x007FF;
pn = LA >> 11;
fn = page_table[pn];
PA = (fn << 11) | dn; // (fn << 11) + d;
6
4. [10 points] Virtual Memory
a. [5points] Consider a demand-paging system where the page fault time (including the times
for looking up page, reading a page from the disk, and updating page table) is on average
30 milliseconds (ms) while the physical memory access time is 10 microsecond (sec).
Addresses are translated through a page table in main memory. So, each memory reference
takes two memory accesses. Assume that 90% of the pages are in the page table while the
10% of the pages cause page fault. [Note: 1 ms = 1000 sec]
Determine the effective Access Time (EAT) for the above system.
in future exams, we may ask include TLB. also ask what should be hit ratio such that EAT <=
4018 ns
b. [5points] Recall that "thrashing" means that a process is busy swapping pages in and out.
Explain the reasons that may cause thrashing and how we can avoid thrashing.
If a process does not have “enough” pages, the page-fault rate is very high.
Degree of multiprogramming is increased too much.
we should give enough pages based on the locality measure minimum number of
pages needed. also monitor the CPU utilization don't simply increase degree of
multiprogramming when cpu util is low, but check if it decreases as multiprog
increses, if so stop multiprogramming.
7
5. [10 points] Threads
Suppose we want a thread to get a structure containing two double values as a parameter and return
another structure containing three types of values as defined below. You are asked to complete the
following program in which the testThread() finds the sum of the received double values and
then returns their sum along with an integer value of 2 and char value of 'p' to the main thread
waiting to join. The main program simply prints out the returned values. You can ignore error
checking. Assume all the necessary libraries are included.
out_data_t *out;
void main() {
pthread_t tid;
double d1= 3.14, d2=5.54; /* double values to be sent to the thread */
8
6. [15 points] Synchronization
a. [10 points] Suppose there are three threads P, Q and R. Each has some sequential code
sections represented as function calls and then updates a shared variable count, as shown
in the below table. Define and initialize semaphores and then solve the coordination and
the critical section problems (use acquire/release or wait/signal). Assume that
RS1() is executed after QS1()which is executed after PS1(),
QS2() is executed after RS1()
PS2() and RS2() are executed after QS2()
/* Semaphores and initial Values: */
S1 = 0; /* can use two sem
but S1 is enough*/
S2 = 0; 2pt
S3 = 0;
S4 = 0; S5 = 1;
P Q R
It is a data structure associated with a mutex and it allows us to atomically unlock the mutex
and block the process. This way we can let other processes to enter the critical section while the
original thread is waiting for a condition. The other threads will change shared variables, and
signal when they are done, so the original process can wake up and check the condition it was
waiting. This helps to avoid busy waiting.
9
7. [10 points] Signals
Suppose we have a program that calls a given function do_something() in an infinite loop.
You are asked to modify/re-implement this program such that it can be terminated gracefully if the
user presses ctrl-c at least three times (recall that pressing ctrl-c generates SIGINT)?
Ignore error checking.
void main(){
struct sigaction act;
act.sa_handler = my_sig_handler;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGINT, &act, NULL);
while(1){
do_something();
if(count >= 3) break;
10
8. [10 points] Communications - implement a client-server program using TCP sockets.
The client will first establish a TCP connection with the server. It then sends two integers (actually
convert them to string and send two strings) and expect server to send back the sum of these
numbers as a string. Upon receiving the sum, the client will print it and quit.
The server always waits for connection requests is an infinite loop. Upon receiving a connection
request, server gets two strings from the client and convert them to umbers. Then finds the sum
and sends it as a string back to client.
When implementing client and server programs below, please focus on the key system calls and in
which order to call them while using generic parameters (e.g., IPaddress, portnum) rather than
actual structures. Also ignore error checking and assume all the necessary libraries are included.
/* server.c */ /* client.c */
int serverIP = 1.1.1.1; int serverIP = 1.1.1.1;
int serverPort = 2017; int serverPort = 2017;
void main(){ void main() {
int welcomeSocket, connSocket; int clientSocket;
int num1, num2, sum; int num1=234, num2=5431, sum;
char buff[10]; char buff[10];
sum = num1+num2;
read(clientSocket, buff,sizeof(buff));
sprintf(buf, "%d", sum); sum = atoi(buf);
write(connSocket, buf, strlen(buf)+1);
printf("Sum of two numbers is %d\n", sum);
close(connSocket);
} close(clientSocket);
close(welcomeSocket); }
}
11