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,下面是xv6Process 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
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/wait.h>

    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()`

未完待续。。。。