CPU는 메모리와 다르게 영역을 작은 piece들로 쪼갤 수 없다. 따라서 많은 프로그램들이 CPU의 전체 영역을 공유하게 된다. 하지만 각 시점에 하나의 프로그램만 CPU를 이용할 수 있다.
한 프로그램만 CPU를 사용할 수 있기 때문에 OS는 많은 CPU가 존재하는 것 같은 illusion을 주어야 한다.
즉 여러 프로그램이 각각 자신의 CPU를 갖고 있는 것 같은 착각을 갖도록 한다.
여기에 필요한 것이 Time sharing
이다.
time sharing은 CPU Virtualization의 key technique이다. 우리는 CPU의 physical area를 sharing할 수는 없지만 time을 sharing할 수는 있다.
긴 시간을 작은 조각으로 쪼개서 각 조각을 하나의 프로그램에게 준다. 그 시간의 조각 동안 한 프로그램을 실행시키고 그 시간이 끝나면 프로그램의 실행을 멈추고 다른 프로그램으로 switch한다. 그리고 그 프로그램의 시간을 다 소모하면 다음 프로그램으로 switch한다. 이를 반복하면 많은 프로그램들이 자신만의 CPU를 소유하고 있다고 생각하도록 만들 수 있다.
time sharing에 드는 potential cost는 performance이다. performance는 switch를 할 때에 드는 overhead의 영향을 받는다.
time sharing을 하기 위해서는 OS가 언제든 running program의 상태를 저장(혹은 캡쳐, resume)할 수 있어야 한다. 프로그램을 실행하고 멈추고를 자유자재로 할 수 있어야 하기 때문...
즉, 이는 OS가 프로그램의 execution을 통제할 수 있어야 함을 의미한다.
프로그램을 멈춰야 한다면 프로그램을 멈춰서 어딘가에(메모리) 저장하고 대기하고 있던 다른 프로그램을 실행시켜야 한다. 따라서 OS는 running program의 상태를 capture 할 수 있어야 한다.
A process is a running program
프로그램이 실행되면 CPU나 메모리의 상태를 바꾸고 때로는 storage(ex. disk)를 바꾸기도 한다.
이 scope를 CPU와 메모리에 한정시키면 프로세스의 상태는 CPU상태와 메모리로 이루어져 있다.
CPU state와 memory를 capture할 수 있다면 running program을 표현할 수 있다.
c = a + b;
와 같이 high-level programming에서는 한 줄로 보이는 코드여도 내부적으로는 load, store등의 여러 instruction이 실행된다. 한 instruction을 실행하면 CPU의 state가 바뀌고(CPU state라는 것은 결국 multiple register이므로 register가 바뀌는 것이다) CPU에서 메모리로 어떤 value를 저장하면 메모리도 바뀐다.
따라서 OS가 CPU와 메모리를 capture할 수 있다면 프로세스를 표현할 수 있게 된다.
CPU가 single instruction을 실행한 직후에는 아무것도 바뀌지 않으므로 그 때 CPU의 state를 저장하면 프로세스를 capture할 수 있다. 나중에 suspend되었던 프로그램을 다시 실행하고 싶으면 메모리에 저장해둔 값을 restore해서 resume하면 된다.
OS는 multiple program이 single CPU에서 동작할 수 있도록 해줌. 각 프로그램이 자신의 own CPU에서 동작하고 있는 듯한 illusion을 주어야 함.
OS는 프로세스를 manage하기 위해서 key data structure를 가지고 있다.
key data structure은 다음으로 이루어져 있다:
PCB는 각 프로세스에 대한 정보를 갖고 있는 C-structure이다.
PCB에는 register variable이 저장되어 있다. CPU의 레지스터 value를 메모리의 PCB에 저장하고 이것이 running program을 stop하는 방법이다.
xv6의 proc이 PCB의 역할을 하고 Linux에서는 이를 task struct라고 한다. 각 OS마다 사용하는 이름은 달라도 같은 컨셉을 사용하고 있다.
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
};
proc
은 PCB이며 PCB는 key structure이다. 가장 먼저 initialize하고 조심히 manage해야 한다. running program을 manage하기 때문이다. 그리고 이것이 CPU virtualization의 key이다.
mem
, sz
, kstack
은 memory state를 capture하는데에 사용된다.
context
는 CPU state를 capture하는데에 사용된다.