OSTEP PartI Virtualization
Don’t let yesterday take up too much of today.
Virtualization
- GCC编译创建线程的代码时需要加
-pthread
参数 Batch processing
: 开始一些作业(jobs)并且然后由接线员来按批运行- 程序是如何转变为进程的。
- 在
Loading
的过程中可以用到lazy,程序在执行时需要这一部分数据才load
到内存中,从而加快加载
的速度。加载到内存中之后,运行main() routine
操作系统将CPU的控制权传给新创建的进程,随后程序开始执行。 - 进程的状态转换
Process List
,记录进程的相关信息(PCB,Process Control Block
)。Process List
的每个条目为PCB
,下面是xv6的Process Structure
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34// the registers xv6 will save and restore
// to stop and subsequently restart a process
struct context {
int eip;
int esp;
int ebx;
int ecx;
int edx;
int esi;
int edi;
int ebp;
};
// the different states a process can be in
enum proc_state { UNUSED, EMBRYO, SLEEPING,
RUNNABLE, RUNNING, ZOMBIE };
// the information xv6 tracks about each process
// including its register context and state
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
};- 上下文切换,如进程A将切换到进程B时,先将
PC
和微体系结构寄存器(e.g. PSR)保存到当前的内核栈,再将当前通用寄存器(i.e. physical registers)的信息save
到进程数据结构中的context
上下文结构体中。随后将进程B的数据结构中的上下文结构信息restore
到当前通用寄存器中,最后从进程B的内核栈中restore
相关PC
和微体系结构寄存器 - 处于
zombile state
的进程(它的父进程未执行wait()
来获取子进程的信息从而指示OS来将它从相关的数据结构中删除)被init
进程接管 fork()
创建子进程后,实际上就是不同的文件描述符指向同一个Open File Table中的条目;调用fork之后父进程返回子进程的PID(Process Identifier)
,而子进程返回0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main(int argc, char *argv[]) {
printf("hello world (pid:%d)\n", (int) getpid());
int rc = fork();
if (rc < 0) { // fork failed; exit
fprintf(stderr, "fork failed\n");
exit(1);
} else if (rc == 0) { // child (new process)
printf("hello, I am child (pid:%d)\n", (int) getpid());
} else { // parent goes down this path (main)
int rc_wait = wait(NULL);
printf("hello, I am parent of %d (rc_wait:%d) (pid:%d)\n",
rc, rc_wait, (int) getpid());
}
return 0;
}
- `exec()`
未完待续。。。。