This page provides an answers for chapter 1 (Introduction) of the book "Modern Operating Systems".
What are the two main functions of an operating system?
In Section 1.4, nine different types of operating systems are described. Give a list of applications for each of these systems (one per operating systems type).
What is the difference between timesharing and multiprogramming systems?
In a timesharing system, multiple interactive users are managed each of which can perform multiprogramming. Multiprogramming simply means multiple processes can run concurrently.
To use cache memory, main memory is divided into cache lines, typically 32 or 64 bytes long. An entire cache line is cached at once. What is the advantage of caching an entire line instead of a single byte or word at a time?
Imagine caching was done with byte level granularity and the user will access 64 bytes contiguously. There will be 64 cache misses. Whereas if the cache lines are 64 bytes then there will be a single cache miss for the first byte at which point the following 63 bytes are cached.
On early computers, every byte of data read or written was handled by the CPU (i.e., there was no DMA). What implications does this have for multiprogramming?
If each byte read/written is managed by the CPU then when multiple processes are running the OS must manage in what order processes receive/send the data requested. This would increase CPU contention tremendously decreasing performance.
Instructions related to accessing I/O devices are typically privileged instructions, that is, they can be executed in kernel mode but not in user mode. Give a reason why these instructions are privileged.
If I/O instructions are available in userspace there is nothing preventing bad (malicious or buggy) processes from incorrectly interacting with devices.
The family-of-computers idea was introduced in the 1960s with the IBM System/360 mainframes. Is this idea now dead as a doornail or does it live on?
This is still alive and well. An example includes the x86 CPU family.
One reason GUIs were initially slow to be adopted was the cost of the hardware needed to support them. How much video RAM is needed to support a 25-line x 80-row character monochrome text screen? How much for a 1200 x 900-pixel 24-bit color bitmap? What was the cost of this RAM at 1980 prices ($5/KB)? How much is it now?
RAM for 25-line x 80-column monochrome text screen: 25 x 80 = 2,000 bytes
RAM for 1200 x 900-pixel 24-bit color bitmap: 1200 x 900 x 3 = 3,240,000 bytes
Assuming decimal kilobytes (1 KB = 1,000 bytes), this is approximately 3,240 KB of memory.
Price for 3,240 KB of memory in 1980 at $5 per KB: $16,200
Price for 3,240 KB of memory in 2025 at $0.00000214577 per KB: approximately $0.00695
There are several design goals in building an operating system, for example, resource utilization, timeliness, robustness, and so on. Give an example of two design goals that may contradict one another.
Correctness and speed (especially in the context of multiprocessor programming).
What is the difference between kernel and user mode? Explain how having two distinct modes aids in designing an operating system.
Kernel mode grants access to specialized CPU instructions only available when the CPU is at a specific ring level.
Kernel level drivers have full responsibility for ensuring devices are used correctly. By decoupling the kernel from userspace, the kernel can provide abstractions (APIs) which userspace programs can use. This allows for the underlying implementation of these APIs to be changed without breaking userspace (most of the time :)...).
A 255-GB disk has 65,536 cylinders with 255 sectors per track and 512 bytes per sector. How many platters and heads does this disk have? Assuming an average cylinder seek time of 11 ms, average rotational delay of 7 msec and reading rate of 100 MB/sec, calculate the average time it will take to read 400 KB from one sector.
Number of platters: (total_data / data_per_platter_side) / 2_sides_per_platter = (255 GB / (65536 * 255 * 512) B) / 2 = 16
Number of heads: 16 * 2 = 32 heads
400 KB / 512 B = ceiling(781.25) = 782 sectors
Average time = 782 * (11 ms + 7 ms + 5.12 * 10^(-6)) = 14.06 sec
This answer assumes sectors are randomly scattered on disk and not contiguous.
Which of the following instructions should be allowed only in kernel mode?
(a) Disable all interrupts.
(b) Read the time-of-day clock.
(c) Set the time-of-day clock.
(d) Change the memory map.
(a) YES
(b) NO
(c) YES
(d) YES
Consider a system that has two CPUs, each CPU having two threads (hyperthreading). Suppose three programs, P0, P1, and P2, are started with run times of 5, 10 and 20 msec, respectively. How long will it take to complete the execution of these programs? Assume that all three programs are 100% CPU bound, do not block during execution, and do not change CPUs once assigned.
The system can run up to 4 threads in parallel.
P0 and P1 finish in 5 and 10 msec respectively. P2 finishes in 20 msec.
Total time: 25 msec
A computer has a pipeline with four stages. Each stage takes the same time to do its work, namely, 1 nsec. How many instructions per second can this machine execute?
Once the pipeline is filled, one instruction completes every 1 nsec.
So the system can execute 1 billion (109) instructions/sec.
Note: the first instruction takes 4 nsec, but this is amortized over many instructions.
Consider a computer system that has cache memory, main memory (RAM), and disk, and an operating system that uses virtual memory. It takes 1 nsec to access a word from the cache, 10 nsec to access a word from the RAM, and 10 ms to access a word from the disk. If the cache hit rate is 95% and main memory hit rate (after a cache miss) is 99%, what is the average time to access a word?
Average access time = (1 ns * 0.95) + ((1 ns + 10 ns)
* 0.99 * 0.05) + ((1 ns + 10 ns + 10 ms) * 0.01 * 0.05)
= 0.95 ns + 0.5445 ns + 5000 ns ≈ 5001.5 ns
When a user program makes a system call to read or write a disk file, it provides an indication of which file it wants, a pointer to the data buffer, and the count. Control is then transferred to the OS, which calls the appropriate driver. Suppose the driver starts the disk and terminates until an interrupt occurs. In the case of reading, the caller blocks. What about writing to the disk? Must the caller be blocked?
No, writing can often be performed asynchronously. The OS may buffer the write and return control to the caller before the physical write completes. The caller can later sync the file system if needed.
What is a trap instruction? Explain its use in operating systems.
A trap instruction switches execution from user mode to kernel mode. It is the mechanism by which system calls are implemented, allowing user programs to request services from the operating system securely.
Why is the process table needed in a timesharing system? Is it also needed in personal computer systems running UNIX or Windows with a single user?
The process table tracks active processes and their states. Even in a single-user system, multiple processes (apps, services) run concurrently, so the OS needs the process table to manage them.
Is there any reason why you might want to mount a file system on a nonempty directory? If so, what is it?
Yes, mounting over a nonempty directory can be used to temporarily hide its contents. This can be useful to mask sensitive or irrelevant files, or to override parts of the directory tree.
For each of the following system calls, give a condition that causes it to fail: fork, exec, and unlink.
fork: Not enough system resources (e.g., memory or process table full).
exec: Executable file is missing, not permitted, or of an unsupported format.
unlink: File does not exist or permission denied.
What type of multiplexing (time, space, or both) can be used for sharing the following resources: CPU, memory, disk, network card, printer, keyboard, and display?
CPU - Time
Memory - Space
Disk - Space
Network Card - Time
Printer - Both
Keyboard - Time
Display - Time
Can the count = write(fd, buffer, nbytes);
call
return any value in count
other than
nbytes
? If so, why?
Yes. If there is insufficient space or an error occurs partway
through, write
may write only some of the bytes
and return the actual number written. The caller must check
the return value.
A file whose file descriptor is fd
contains the following bytes: 3, 1, 4, 1, 5,
9, 2, 6, 5, 3, 5. The following system calls are made:
lseek(fd, 3, SEEK_SET);
read(fd, &buffer, 4);
What does buffer contain after the read has completed?
The seek moves the file pointer to byte 3 (zero-indexed), which contains the value 1.
Reading 4 bytes gives: 1, 5, 9, 2
So buffer
contains: 1, 5, 9, 2
move_to_cylinder + move_to_track + read_bytes
(50 x 1 ms) + 5 ms + (10 MB / 200 MB/s)
= 0.05 s + 0.005 s + 0.05 s = 0.105 seconds
Block special files work on blocks of data at a time, while character special files work on characters of data at a time.
No, the library procedure name is more important for the users of the system.
Each process thinks it has access to the full memory space. Pages can be loaded and unloaded to and from disk while a process is running. This allows many large processes to run simultaneously, since only a subset of their data is actually in memory at any one time.
Yes, syscalls have performance implications. It is useful to know which functions invoke syscalls when optimizing for performance or debugging.
link: May have to copy data and ensure consistency.
mount: Cannot have a single filesystem tree.
umount: Same limitation as mount.
chmod: Use `icacls` instead.
kill: Use `taskkill`.
execve: Fork and exec is a single call in Windows now.
New CPU architectures are introduced frequently.
Syscall API: Not always trapping to the kernel.
Device drivers: These interact with hardware
controllers and are often architecture-specific.
Microservices declare the policy they want. Services responsible for handling it then determine how to implement it (the mechanism). Separating policy and mechanism allows mechanism implementations to reside in the kernel, increasing stability and flexibility.
They take a long time to boot (hence the popularity of containers) and also suffer from a runtime performance hit.
(a) Nanoyear = 0.0315576 seconds
(b) Megamicron = 1 meter
(c) 1 PB = 1,000,000,000,000,000 bytes
(d) 6000 yottagrams = 6 x 1024 kilograms
Still in progress...
Github Link
#include <stdio.h> #include <unistd.h> #include <sys/wait.h> static void recurse_fork() { pid_t pid = fork(); int wait_stat; if(pid == 0) recurse_fork(); else wait(&wait_stat); } int main() { recurse_fork(); return 0; }
Viewed... Moving on.