update 8.md 9.md
This commit is contained in:
203
notes/9.md
Normal file
203
notes/9.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Exception
|
||||
|
||||
An Exception is a **transfer of control** to the OS kernel in response to some event(like div by 0, overflow, ctrl+C). that is change in processor state.
|
||||
|
||||
**Exception Tables**
|
||||
|
||||
Each type of event has an unique exc number `k`: `k` is index into **exception table(interrupt vector table)**
|
||||
|
||||
Handler `k` is called each time exception `k` occurs.
|
||||
|
||||
## Asyncronous exceptions
|
||||
|
||||
It is caused by external events. Handler returns to next instruction.
|
||||
|
||||
for example: Timer interrupt, I/O interrupt.
|
||||
|
||||
## Syncronous exceptions
|
||||
|
||||
It is caused by events that occur as a result of exxecuting an current instruction.
|
||||
|
||||
* Traps
|
||||
* Intentional like procedure calls (e.g. system calls)
|
||||
* Returns to next instruction
|
||||
* Faults
|
||||
* Unintentional but possibly recoverable (e.g. page fault(recoverable), protection fault(not recoverable), floating point exception)
|
||||
* re-executes by kernel or aborts
|
||||
* Aborts
|
||||
* Unintentional and not recoverable (e.g. illegal instruction, parity error, machine check)
|
||||
* Aborts the program
|
||||
|
||||
## System Calls
|
||||
|
||||
Each x86-64 system call has a unique syscall number.
|
||||
|
||||
| Num | Name | Desc |
|
||||
| --- | ------ | --------------- |
|
||||
| 0 | read | read file |
|
||||
| 1 | write | write file |
|
||||
| 2 | open | open file |
|
||||
| 3 | close | close file |
|
||||
| 4 | stat | get file status |
|
||||
| 57 | fork | create process |
|
||||
| 59 | execve | execute program |
|
||||
| 62 | kill | send signal |
|
||||
|
||||
## Fault Example
|
||||
|
||||
### Page Fault
|
||||
```c
|
||||
int a[1000];
|
||||
main() {
|
||||
a[500] = 13;
|
||||
}
|
||||
```
|
||||
In this situation, a page containing `a[500]` is currently on disk, so page fault occurs, CPU cannot find the data in physical RAM. So kernel copy page from disk to memory, and return and re-executes the instruction `movl`
|
||||
|
||||
### Invalid Memory Ref
|
||||
|
||||
```c
|
||||
int a[1000];
|
||||
main() {
|
||||
a[5000] = 13;
|
||||
}
|
||||
```
|
||||
|
||||
In this situation, address `a[5000]` is invalid, so protection fault occurs, kernel terminates the program by sending `SIGSEGV` signal to the user process. Then user process exits with error code `Segmentation Fault`.
|
||||
|
||||
|
||||
## Process
|
||||
|
||||
An instance of a running program.
|
||||
|
||||
Process provides each program with two key abstractions:
|
||||
* Logical control flow
|
||||
* Each program seems to have **exclusive use of the CPU** provided by **context switching** of the kernel
|
||||
* Private address space
|
||||
* Each program seems to have **exclusive use of main memory** provided by **virtual memory** of the kernel
|
||||
|
||||
But in reality, computer runs multiple processes simultaneously by time-sharing CPU and multiplexing memory.
|
||||
|
||||
### Multiprocessing
|
||||
|
||||
Single processor executes multiple processes concurrently. process execution interleaved by time-slicing. Address spaces managed by virtual memory system. And register values for non-executing processes saved in memory.
|
||||
|
||||
Multicore processor share main memory each can execute a separate process. scheduling of processors onto cores done by kernel.
|
||||
|
||||
### Concurrent Processes
|
||||
|
||||
Concurrency is **not at the exact same time**.
|
||||
|
||||
Two processes are **concurrent** if their flows **overlap in time**. Otherwise, they are **sequential**.
|
||||
|
||||
Control flows for concurrent processes are pysically disjoint in time. But user think that they are logically running in parallel.
|
||||
|
||||
* Execution time of instruction may vary because of the Nondeterminism of the System: OS scheduling, Interrupts, Cache miss or Page fault, I/O device delays.
|
||||
|
||||
### Context Switching
|
||||
|
||||
Prcess are managed by a shared chunk of memory-resident OS code called the **kernel**.
|
||||
|
||||
What is important is that the kernel is **not a seprate process**. It is invoked by processes when they need OS services, or when exceptions occur. That is Part of the processor.
|
||||
|
||||
Control flow passes via a context switching.
|
||||
|
||||
## Syscall Error Handling
|
||||
|
||||
On error, Linux sys level function typically returns `-1` and sets the global variable `errno` to indicate the specific error.
|
||||
|
||||
Hard and fast rule:
|
||||
* You must check the return status of every system-level function
|
||||
* Only exception is the handful of functions that return void
|
||||
|
||||
Error reporting functions:
|
||||
```c
|
||||
void unix_error(char *msg) {
|
||||
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
|
||||
exit(0);
|
||||
}
|
||||
```
|
||||
|
||||
Error handling wrappers:
|
||||
```c
|
||||
pid_t Fork(void) {
|
||||
pid_t pid;
|
||||
if ((pid = fork()) < 0) unix_error("Fork error");
|
||||
return pid;
|
||||
}
|
||||
```
|
||||
|
||||
## Creating and Terminating Processes
|
||||
|
||||
* `pid_t getpid(void)` returnes pid of current process
|
||||
* `pid_t getppid(void)` returns pid of parent process
|
||||
|
||||
We can think of a process as being in one of three states:
|
||||
* Running
|
||||
* Executing or waiting to be executed
|
||||
* Stopped
|
||||
* Process execution is suspended and will not be scheduled until futher notice
|
||||
* Terminated
|
||||
* Stopped permanently
|
||||
|
||||
### Terminating Processes
|
||||
|
||||
1. `return` from `main`
|
||||
2. call `exit(status)` function
|
||||
3. Receive a termination signal
|
||||
|
||||
```c
|
||||
void exit(int status);
|
||||
```
|
||||
|
||||
### Creating Process
|
||||
|
||||
Parent process can creates a new running child process by calling `fork()` system call.
|
||||
|
||||
```c
|
||||
int fork(void);
|
||||
```
|
||||
|
||||
it returns `0` to the newly created child, and returns **child's pid** to the parent.
|
||||
Child is almost identical to parent: child get an identical copy of the parent's virtual address space, file descriptors, and process state.
|
||||
But child has its own unique pid.
|
||||
|
||||
```c {cmd=gcc, args=[-O2 -x c $input_file -o 9_1.out]}
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
int main() {
|
||||
pid_t pid;
|
||||
int x = 1;
|
||||
pid = fork();
|
||||
if (pid == 0) { /* Child */
|
||||
printf("child: x=%d\n", ++x);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
printf("parent: x=%d\n", --x);
|
||||
exit(0);
|
||||
}
|
||||
```
|
||||
|
||||
```sh {cmd}
|
||||
while ! [ -r 9_1.out ]; do sleep .1; done; ./9_1.out
|
||||
```
|
||||
|
||||
Concurrent execution of parent and child processes. `fork` duplicates but separates address space.
|
||||
File descriptors are shared between parent and child like `stdout`, `stderr`.
|
||||
|
||||
Modeling fork with Process Graphs
|
||||
* Each vertex represents a process state
|
||||
* Directive Edges represent is ordering of execution.
|
||||
* Edge can be labeled with current value of variables
|
||||
|
||||
Any topological sort of the graph corresponds to a feasible total ordering.
|
||||
|
||||
|
||||
### Reaping Child Processes
|
||||
|
||||
When a child process terminates, it becomes a **zombie** until its parent calls `wait` to read its exit status.
|
||||
|
||||
## execve
|
||||
|
||||
Reference in New Issue
Block a user