[Operating Systems: Three Easy Pieces] (http://pages.cs.wisc.edu/~remzi/OSTEP/)
it is a running program
but the program is a lifeless thing:it just sits there on the disk,a bunch of instructions
1、what constitute a process?
memory (instructions,the data that the running process reads and writes)
registers
program counter(PC) stack pointer frame pointer
2、process API
create
destroy
wait
status
control(suspend a process and resume the process)
3、process creation:a little more detail
How programs are transformed into processes?
programs initially reside on disk.
load its code and any static data into memory.
some memory must be allocated (by OS) for the program’s run-time stack.
The OS also allocate some memory for the program’s heap.
The OS will also do some other initialization task. (examples: three file descriptors(input,output,error) )
The OS set the stage for program execution,to start the program at the entry point,namely main()
the OS transfer control of the CPU to the newly-created process
4、process states
Running
Ready
Blocked
5、data structures
The OS is a program, and like any program, it has some key data Structures that track various relevant pieces of information.
To track the state of each process
keep some kind of processlist for all processes that are ready,running,blocked
Process List
struct proc {
char *mem; // Start of process memory
uint sz; // Size of process memory
char *kstack; // Bottom of kernel stack
// for this process
enum proc_state state; // Process state
int pid; // Process ID
struct proc *parent; // Parent process
void *chan; // If non-zero, sleeping on chan
int killed; // If non-zero, have been killed
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
struct context context; // Switch here to run process
struct trapframe *tf; // Trap frame for the
// current interrupt
};
struct context {
int eip;
int esp;
int ebx;
int ecx;
int edx;
int esi;
int edi;
int ebp;
};
1、fork()
The fork() system call is used to create a new process
2、wait()
the parent process calls wait() to delay its execution until the child finishes executing
3、exec()
it loads code (and static data) from that executable and overwrites its current code segment (and current static data) with it; the heap and stack and other parts of the memory space of the program are re-initialized.
it does not create a new process; rather, it transforms the currently running program (formerly p3) into a different running program
4、why would we build such an odd interface to what should be the simple act of creating a new process?
the separation of fork() and exec() is essential in building a UNIX shell, because it lets the shell run code after the call to fork() but before the call to exec(); this code can alter the environment of the about-to-be-run program, and thus enables a variety of interesting features to be readily built.
5、Other Parts Of The API
kill()
shell:ps top
The basic idea is simple: run one process for a little while, then run another one, and so forth.
By time sharing the CPU in this manner,virtualization is achieved.
a few challenges: performance and control
Control is particularly important to the OS, as it is in charge of resources;
without control, a process could simply run forever and take over the machine, or access information that it should not be allowed to access.
1、Basic Technique: Limited Direct Execution
The “direct execution” part of the idea is simple: just run the program directly on the CPU.
Rise to a few problems:
The first is simple: if we just run a program, how can the OS make sure the program doesn’t do anything that we don’t want it to do
The second:when we are running a process, how does the operating system stop it from running and switch to another process
what if the process wishes to perform some kind of restricted operation, such as issuing an I/O request to a disk, or gaining access to more system resources such as CPU or memory?
Approach:
1、we can’t simply let any user process issue I/Os to the disk; if we did, a process could simply read or write the entire disk and thus all protections would be lost
2、the approach we take is to introduce a new processor mode,known as user mode.
code that runs in user mode is restricted in what it can do. For example, when running in user mode, a process can’t issue I/O requests
3、In contrast to user mode is kernel mode, which the operating system (or kernel) runs in.
In this mode, code that runs can do what it likes, including privileged operations such as issuing I/O requests and executing all types of restricted instructions
4、user mode call System Call ,then go to kernel mode
To execute a system call, a program must execute a special trap instruction
jumps into the kernel and raises the privilege level to kernel mode
do the required work for the calling process
the OS calls a special return-from-trap instruction
returns into the calling user program while simultaneously reducing the privilege level back to user mode.
Some detail: How does the trap know which code to run inside the OS?
thinking: Clearly, the calling process can’t specify an address to jump to (as you would when making a procedure call); doing so would allow programs to jump anywhere into the kernel which clearly is a Very Bad Idea.
Thus the kernel must carefully control what code executes upon a trap.
1、The kernel does so by setting up a trap table at boot time
2、One of the first things the OS thus does is to tell the hardware what code to run when certain exceptional events occur. The OS informs the hardware of the locations of these trap handlers
To specify the exact system call, a system-call number is usually assigned to each system call.
The user code is thus responsible for placing the desired system-call number in a register or at a specified location on the stack;
user code cannot specify an exact address to jump to, but rather must request a particular service via number
a privileged operation:being able to execute the instruction to tell the hardware where the trap tables are is a very powerful capability.
Why have this problem?
The OS should just decide to stop one process and start another,sounds simple?
But it actually is a little bit tricky: specifically, if a process is running on the CPU, this by definition means the OS is not running.
If the OS is not running, how can it do anything at all? (hint: it can’t)
Approach #1:Wait For System Calls (A Cooperative Approach)
the OS regains control of the CPU by waiting for a system call or an illegal operation of some kind to take place.
so the process transfer control to the OS so it can run other processesBut,if a process (whether malicious,or just full of bugs) ends up in an infinite loop, and never makes a system call? What can the OS do then?
Approach #2:The OS Takes Control(A Non-Cooperative Approach)
thinking:In Approach #1,when a process gets stuck in an infinite loop is to resort to the age-old solution to all problems in computer systems: reboot the machine.
HOW TO GAIN CONTROL WITHOUT COOPERATION
1、 a timer interrupt.
A timer device can be programmed to raise an interrupt every so many milliseconds
when the interrupt is raised, the currently running process is halted, and a pre-configured interrupt handler in the OS runs
At this point, the OS has regained control of the CPU, and thus can do what it pleases: stop the current process, and start a different one