This will be very brief. Much of the rest of the course will consist in “filling in the details”.
A program in execution. If you run the same program twice, you have created two processes. For example if you have two editors running in two windows, each instance of the editor is a separate process.
Often one distinguishes the state or context (memory image, open files) from the thread of control. Then if one has many threads running in the same task, the result is a “multithreaded processes”.
The OS keeps information about all processes in the process table. Indeed, the OS views the process as the entry. This is an example of an active entity being viewed as a data structure (cf. discrete event simulations). An observation made by Finkel in his (out of print) OS textbook.
A process can send a signal to another process to cause the latter to execute a predefined function (the signal handler). This can be tricky to program since the programmer does not know when in his “main” program the signal handler will be invoked.
Each user is assigned User IDentification (UID) and all processes created by that user have this UID. One UID is special (the superuser or administrator) and has extra privileges. A child has the same UID as its parent. It is sometimes possible to change the UID of a running process. A group of users can be formed and given a Group IDentification, GID.
Access to files and devices can be limited to a given UID or GID.
A set of processes each of which is blocked by a process in the
set. The automotive equivalent, shown at right, is gridlock.
Each process requires memory. The linker produces a load module that assumes the process is loaded at location 0. The operating system ensures that the processes are actually given disjoint memory. Current operating systems permit each process to be given more (virtual) memory than the total amount of (real) memory on the machine.
There are a wide variety of I/O devices that the OS must manage. For example, if two processes are printing at the same time, the OS must not interleave the output. The OS contains device specific code (drivers) for each device as well as device-independent I/O code.
Modern systems have a hierarchy of files. A file system tree.
You can name a file via an absolute path starting at the root directory or via a relative path starting at the current working directory.
In addition to regular files and directories, Unix also uses the file system namespace for devices (called special files, which are typically found in the /dev directory. Often utilities that are normally applied to (ordinary) files can be applied as well to some special files. For example, when you are accessing a unix system using a mouse and do not have anything serious going on (e.g., right after you log in), type the following command
cat /dev/mouseand then move the mouse. You kill the cat by typing cntl-C. I tried this on my linux box and no damage occurred. Your mileage may vary.
Before a file can be accessed, it must be opened and a file descriptor obtained. Subsequent I/O system calls (e.g., read and write) use the file descriptor rather that the file name. This is an optimization that enables the OS to find the file once and save the information in a file table accessed by the file descriptor. Many systems have standard files that are automatically made available to a process upon startup. These (initial) file descriptors are fixed.
A convenience offered by some command interpretors is a pipe or pipeline. The pipeline
dir | wcwhich pipes the output of dir into a character/word/line counter, will give the number of files in the directory (plus other info).
Files and directories have associated permissions.
Security has of course sadly become a very serious concern. The topic is very serious and I do not feel that the necessarily superficial coverage that time would permit is useful so we are not covering the topic at all.
The command line interface to the operating system. The shell permits the user to
Homework: 8
System calls are the way a user (i.e., a program) directly interfaces with the OS. Some textbooks use the term envelope for the component of the OS responsible for fielding system calls and dispatching them to the appropriate component of the OS. On the right is a picture showing some of the OS components and the external events for which they are the interface.
Note that the OS serves two masters. The hardware (below) asynchronously sends interrupts and the user synchronously invokes system calls and generates page faults.
Homework: 14
What happens when a user executes a system call such as read()? We show a more detailed picture below, but at a high level what happens is
The following actions occur when the user executes the (Unix) system call
count = read(fd,buffer,nbytes)which reads up to nbytes from the file described by fd into buffer. The actual number of bytes read is returned (it might be less than nbytes if, for example, an eof was encountered).
A major complication is that the system call handler may block.
Indeed for read it is likely that a block will occur. In that case a
switch occurs to another process. This is far from trivial and is
discussed later in the course.
Process Management | ||
---|---|---|
Posix | Win32 | Description |
Fork | CreateProcess | Clone current process |
exec(ve) | Replace current process | |
waid(pid) | WaitForSingleObject | Wait for a child to terminate. |
exit | ExitProcess | Terminate current process & return status |
File Management | ||
Posix | Win32 | Description |
open | CreateFile | Open a file & return descriptor |
close | CloseHandle | Close an open file |
read | ReadFile | Read from file to buffer |
write | WriteFile | Write from buffer to file |
lseek | SetFilePointer | Move file pointer |
stat | GetFileAttributesEx | Get status info |
Directory and File System Management | ||
Posix | Win32 | Description |
mkdir | CreateDirectory | Create new directory |
rmdir | RemoveDirectory | Remove empty directory |
link | (none) | Create a directory entry |
unlink | DeleteFile | Remove a directory entry |
mount | (none) | Mount a file system |
umount | (none) | Unmount a file system |
Miscellaneous | ||
Posix | Win32 | Description |
chdir | SetCurrentDirectory | Change the current working directory |
chmod | (none) | Change permissions on a file |
kill | (none) | Send a signal to a process |
time | GetLocalTime | Elapsed time since 1 jan 1970 |
The table on the right shows some systems calls; the descriptions are accurate for Unix and close for win32. To show how the four process management calls enable much of process management, consider the following highly simplified shell. (The fork() system call returns true in the parent and false in the child.)
while (true) display_prompt() read_command(command) if (fork() != 0) waitpid(...) else execve(command) endif endwhile
Simply removing the waitpid(...) gives background jobs.
Homework: 18.
The transfer of control between user processes and the operating system kernel can be quite complicated, especially in the case of blocking system calls, hardware interrupts, and page faults. Before tackling these issues later, we begin with the familiar example of a procedure call within a user-mode process.
An important OS objective is that, even in the more complicated cases of page faults and blocking system calls requiring device interrupts, simple procedure call semantics are observed from a user process viewpoint. The complexity is hidden inside the kernel itself, yet another example of the operating system providing a more abstract, i.e., simpler, virtual machine to the user processes.
More details will be added when we study memory management (and know officially about page faults) and more again when we study I/O (and know officially about device interrupts).
A number of the points below are far from standardized. Such items as where are parameters placed, which routine saves the registers, exact semantics of trap, etc, vary as one changes language/compiler/OS. Indeed some of these are referred to as “calling conventions”, i.e. their implementation is a matter of convention rather than logical requirement. The presentation below is, we hope, reasonable, but must be viewed as a generic description of what could happen instead of an exact description of what does happen with, say, C compiled by the Microsoft compiler running on Windows XP.
We mean one procedure running in kernel mode calling another procedure, which will also be run in kernel mode. Later, we will discuss switching from user to kernel mode and back.
There is not much difference between the actions taken during a kernel-mode procedure call and during a user-mode procedure call. The procedures executing in kernel-mode are permitted to issue privileged instructions, but the instructions used for transferring control are all unprivileged so there is no change in that respect.
One difference is that often a different stack is used in kernel mode, but that simply means that the stack pointer must be set to the kernel stack when switching from user to kernel mode. But we are not switching modes in this section; the stack pointer already points to the kernel stack. Often there are two stack pointers one for kernel mode and one for user mode.
Process P, running in unprivileged (user) mode, executes a trap. The code being executed was written in assembler since there are no high level languages that generate a trap instruction. There is no need to name the function that is executing. Compare the following example to the explanation of “f calls g” given above.
interruptis used because an RTI is used when the kernel is returning from an interrupt as well as the present case when it is returning from an trap.
Remark: A good way to use the material in the addendum is to compare the first case (user-mode f calls user-mode g) to the TRAP/RTI case line by line so that you can see the similarities and differences.
I must note that Tanenbaum is a big advocate of the so called microkernel approach in which as much as possible is moved out of the (supervisor mode) kernel into separate processes. The (hopefully small) portion left in supervisor mode is called a microkernel.
In the early 90s this was popular. Digital Unix (now called True64) and Windows NT/2000/XP are examples. Digital Unix is based on Mach, a research OS from Carnegie Mellon university. Lately, the growing popularity of Linux has called into question the belief that “all new operating systems will be microkernel based”.
The previous picture: one big program
The system switches from user mode to kernel mode during the poof and then back when the OS does a “return” (an RTI or return from interrupt).
But of course we can structure the system better, which brings us to.
Some systems have more layers and are more strictly structured.
An early layered system was “THE” operating system by Dijkstra. The layers were.
The layering was done by convention, i.e. there was no enforcement by hardware and the entire OS is linked together as one program. This is true of many modern OS systems as well (e.g., linux).
The multics system was layered in a more formal manner. The hardware provided several protection layers and the OS used them. That is, arbitrary code could not jump to or access data in a more protected layer.
Use a “hypervisor” (beyond supervisor, i.e. beyond a normal OS) to switch between multiple Operating Systems. Made popular by IBM's VM/CMS
Similar to VM/CMS but the virtual machines have disjoint resources (e.g., distinct disk blocks) so less remapping is needed.
When implemented on one computer, a client-server OS uses the microkernel approach in which the microkernel just handles communication between clients and servers, and the main OS functions are provided by a number of separate processes.
This does have advantages. For example an error in the file server cannot corrupt memory in the process server. This makes errors easier to track down.
But it does mean that when a (real) user process makes a system call there are more processes switches. These are not free.
A distributed system can be thought of as an extension of the client server concept where the servers are remote.
Today with plentiful memory, each machine would have all the different servers. So the only reason a message would go to another computer is if the originating process wished to communicate with a specific process on that computer (for example wanted to access a remote disk).
Homework: 23
Dennis Ritchie, the inventor of the C programming language and co-inventor, with Ken Thompson, of Unix was interviewed in February 2003. The following is from that interview.
What's your opinion on microkernels vs. monolithic?
Dennis Ritchie: They're not all that different when you actually use them. "Micro" kernels tend to be pretty large these days, and "monolithic" kernels with loadable device drivers are taking up more of the advantages claimed for microkernels.