April 2, 2019
For today:
0) Finish the matrix exercise
1) Finish Homework 7
2) Read Think OS Chapter 8 and do the reading quiz
3) Project 2 proposal
Today:
1) Homework 8 intro: GLib
2) Think OS Chapter 8
3) HFC Chapter 9 preview
No class Friday
For next Tuesday:
1) Do Homework 8 (due Tuesday evening)
2) Read HFC Chapter 9
3) Work on your project
4) Prepare for a quiz (here's last year's quiz for practice)
Note: I made some changes in the calendar spreadsheet (the previous version had a class this Friday)
Project 2 suggestions:
1) Aim for 2-4 hours per person per week.
2) Schedule some team time and some solo time each week.
3) Divide work so you can be productive individually.
4) Keep Trello up to date (primarily for your benefit, but also so I can see what's happening).
5) Make consistent effort.
6) Make your effort effective.
Consider a longer session early on to establish a "beachhead".
Books on hold in the library:
Using GLib
The challenges of this exercise include:
1) Installing GLib and getting Hello GLib to compile and run.
2) Reading GLib documentation and figuring out how to map Python data structures to C code.
3) Getting comfortable with some C syntax/semantics idioms for object-oriented programming, like void pointers and function pointers.
I didn't provide a lot of scaffolding because there's a lot of meta-cognition going on here:
1) Meta-debugging: reflecting on your processes for getting things working, being aware of your strategies and which ones are working, or not.
2) Explore vs exploit decisions: when should you persevere and when you should pivot?
In grad school and first jobs, these are among the skills that distinguish people who can Get Things Done.
Consider reading This blog article on the pains of the command line and this rebuttal.
Exercise: try strace, as described by the inimitable Julia Evans.
Warning: The presentation on page 398 of HFC confuses two very different things:
1) System call: Similar to a function call, but an application causes an exception (usually by executing a protected instruction) in order to jump into kernel code. An interrupt handler executes code (in kernel mode) on behalf of the process, then jumps back into the application code.
2) The C library function system(), which spawns a child process and uses it to execute a shell command, which spawns a child process to execute the command.
These two things are very, very different!
And it's even more confusing because in UNIX, many of the library functions that are called system calls are actually "user code sandwiches".
That is, they are library functions that run some user code to get things set up, THEN make a real system call (or more than one), and then run some user code to prepare a return value and/or error code.
For more about this, and a list of Linux system calls, see this man page.
Making a system call generally does not create a new process. All it does is run some kernel code on your behalf.
The exception is fork, which does create a process.
At heart, a kernel is a glorified interrupt handler.
What are some of the things that cause interrupts?
The mode bit indicates whether a program is running in user mode or kernel mode. In kernel mode we can execute all instructions; in user mode, protected instructions cause an interrupt.
Sequence of events when an interrupt occurs:
1) The hardware saves enough hardware state to allow the interrupted process to resume, then jumps to the appropriate interrupt handler.
2) The interrupt handler stores any additional state it has to (for example, any data registers it plans to use).
3) The interrupt handler runs whatever code is needed to handle the interrupt.
4) Then it restores the contents of the saved registers. Finally, it restores the program counter of the interrupted process, which has the effect of jumping back to the interrupted instruction.
One of the things an interrupt handler might do is invoke the scheduler, which decides which process to run next.
If the selected process is not the process that was running, we have to do a context switch.
Why is a context switch generally more expensive than a normal interrupt?
Processes are generally in one of four states:
1) Running
2) Ready
3) Blocked
4) Done
Exercise: Draw a state transition diagram that shows these states and what events cause a process to move from one state to another.
Processes can be
1) CPU bound: more CPU time makes them finish faster
2) I/O bound: they spend time waiting, more CPU doesn't help
As a general heuristic, schedulers try to give priority to I/O bound processes:
1) If you are going to wait for a request to complete, initiate it as soon as possible.
2) If a process is likely to yield the CPU quickly, letting it go first minimizes mean time to completion.
But processes don't announce whether they are I/O or CPU bound; the scheduler has to infer. Hence the following guidelines:
1) Give a new process high priority.
2) If a process blocks before it uses a quantum, increase its priority.
3) If it uses an entire quantum, lower its priority.
4) When a blocked process becomes ready, schedule it asap.
5) If A is blocked waiting for B, give B more priority.
These guidelines are based on the heuristic that the past repeats; that is, if a process just did I/O, it is likely to do so again. If a process has been running for a long time, it is likely to continue running.
The distribution of process lifetimes is long-tailed; as a results, processes have the UBNE property, like some electronic components, cancer patients, and new motorcyclists.
Exercise: When I make French toast, I usually make a batch of 12 slices. But my griddle only has room for 8 slices. Each piece of toast has to cook for 5 minutes on each side. How can I schedule 12 slices onto 8 "cores" to minimize the elapsed time to cook all 12 slices?
(Note: this question is not hypothetical; this is really how I make French toast.)