Weekly Notes for Week 09
-
In the lecture on Feb 25th, we will finish the discussion on Chapter 3. Examples will be shown for implementation and usage of ordinary pipes and named pipes. Examples will be shown for implementation and usage of socket programming.
-
We will start with Chapter 4 (Threads and Concurrency), which will also be the main topic of the lecture on Thursday. Next week we will start with Chapter 5 (Scheduling).
-
For Chapters 3 and 4 examples were be shown illustrating the difference of fork, vfork, and clone on Linux systems.
-
For Chapters 3 and 4 examples will be shown of how to implement signal handlers. Examples will be shown of how to use OpenMP and pthreads.
Tutorial Session Week 09
Prepare for the Tutorial Session in Week 09 from Chapter 3 the following exercises,
- Using the program shown below, explain what the output will be at
LINE A
.#include <sys/types.h> #include <stdio.h> #include <unistd.h> int value = 5; int main() { pid t pid; pid = fork(); if (pid == 0) { /* child process */ value += 15; return 0; } else if (pid > 0) { /* parent process */ wait(NULL); printf("PARENT: value = %d",value); /* LINE A */ return 0; } }
- Including the initial parent process, how many processes are created by the program shown below?
#include <stdio.h> #include <unistd.h> int main() { /* fork a child process */ fork(); /* fork another child process */ fork(); /* and fork another */ fork(); return 0; }
-
Original versions of Apple’s mobile iOS operating system provided no means of concurrent processing. Discuss three major complications that concurrent processing adds to an operating system.
-
Some computer systems provide multiple register sets. Describe what happens when a context switch occurs if the new context is already loaded into one of the register sets. What happens if the new context is in memory rather than in a register set and all the register sets are in use?
- When a process creates a new process using the
fork()
operation, which of the following states is shared between the parent process and the child process?- Stack
- Heap
- Shared memory segments
-
Consider the “exactly once”-semantic with respect to the RPC mechanism. Does the algorithm for implementing this semantic execute correctly even if the ACK message sent back to the client is lost due to a network problem? Describe the sequence of messages, and discuss whether “exactly once” is still preserved.
-
Assume that a distributed system is susceptible to server failure. What mechanisms would be required to guarantee the “exactly once” semantic for execution of RPCs?
-
Describe the actions taken by a kernel to context-switch between processes.
- Including the initial parent process, how many processes are created by
the program shown below.
#include <stdio.h> #include <unistd.h> int main() { int i; for (i = 0; i < 4; i++) fork(); return 0; }
- Using the program below, identify the values of pid at lines A , B ,
C , and D . (Assume that the actual pids of the parent and child are 2600
and 2603, respectively.)
#include <sys/types.h> #include <stdio.h> #include <unistd.h> int main() { pid t pid, pid1; /* fork a child process */ pid = fork(); if (pid < 0) { /* error occurred */ fprintf(stderr, "Fork Failed"); return 1; } else if (pid == 0) { /* child process */ pid1 = getpid(); printf("child: pid = %d",pid); /* A */ printf("child: pid1 = %d",pid1); /* B */ } else { /* parent process */ pid1 = getpid(); printf("parent: pid = %d",pid); /* C */ printf("parent: pid1 = %d",pid1); /* D */ wait(NULL); } return 0; }
-
Give an example of a situation in which ordinary pipes are more suitable than named pipes and an example of a situation in which named pipes are more suitable than ordinary pipes.
- Using the program shown below, explain what the output will
be at lines X and Y.
#include <sys/types.h> #include <stdio.h> #include <unistd.h> #define SIZE 5 int nums[SIZE] = {0,1,2,3,4}; int main() { int i; pid t pid; pid = fork(); if (pid == 0) { for (i = 0; i < SIZE; i++) { nums[i] *= -i; printf("CHILD: %d ",nums[i]); /* LINE X */ } } else if (pid > 0) { wait(NULL); for (i = 0; i < SIZE; i++) printf("PARENT: %d ",nums[i]); /* LINE Y */ } return 0; }
- What are the benefits and the disadvantages of each of the following?
Consider both the system level and the programmer level.
- Synchronous and asynchronous communication
- Automatic and explicit buffering
- Send by copy and send by reference
- Fixed-sized and variable-sized messages
- What is the following bpftrace one-liner doing? What is the output you would expect?
bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @ = count(); } interval:s:1 { print(@); clear(@); }'
- Discuss the following code of a bpftrace (resp. DTrace) script.
interval:s:1
(resp.profile:::tick-1sec
) tells bpftrace (resp. DTrace) to create a new probe which fires once per second. What are the probes, what are the filters, and what are the actions of the bpftrace script? What happens on execution and what is the output of the program? wrt DTrace: the functiontrace()
indicates that DTrace should record the specific argument and print it out.BEGIN { @i = 10; } interval:s:1 /@i > 0/ { @i--; printf("Tick %d\n",@i); } interval:s:1 /@i == 0/ { printf("blastoff!"); exit(); }
dtrace:::BEGIN { i = 10; } profile:::tick-1sec /i > 0/ { trace(i--); } profile:::tick-1sec /i == 0/ { trace("blastoff!"); exit(0); }
C Programming
Analyse the following C program(s), and discuss the code given below wrt. correctness, readability and efficiency of the code. Is the first version more efficient than the naïve recursive approach (2nd version) to compute the power of a number?
/* Version 1 */
#include <stdio.h>
#include <inttypes.h>
float power(float x, uint32_t exp);
float power(float x, uint32_t exp)
{
float result;
/* base case */
if (exp == 0)
return 1.0;
result = power(x, exp >> 1);
result = result * result;
if (exp & 1)
result = result * x;
return result;
}
int main(int argc, char **argv)
{
float p;
p = power(10.0, 5);
printf("p = %f\n", p);
return 0;
}
/* Version 2 */
#include <stdio.h>
#include <inttypes.h>
float power(float x, uint32_t exp)
{
/* base case */
if (exp == 0) {
return 1.0;
}
/* recursive case */
return x*power(x, exp - 1);
}
int main(int argc, char **argv)
{
float p;
p = power(10.0, 5);
printf("p = %f\n", p);
return 0;
}