2019030991 홍정범

과제를 시작하기에 앞서 그래서 xv6가 어떻게 실행되는데..? 라는 생각에 한 공부


Booting

PC powers on -> load bootloader(bootasm.S, bootmain.c) -> load kernel -> execute kernel entry

컴퓨터가 켜지면 각종 하드웨어를 초기화하고 부트로더를 실행. 그리고 이 부트로더가 커널 이미지를 디스크의 첫번째 섹터에 위치시켜준다. 그 후 부트로더가 xv6의 entry에 진입함으로써 xv6 커널이 실행시작. 이제 main.c로 진입.

Creating First user-level Process

main.c의 kini1() 함수부터 kinit2() 함수까지는 하드웨어 자원가 xv6 커널에 대한 초기화 작업.

첫번째 user-process는 userinit() 함수로 생성되고 mpmain()함수로 실행됨.


자자, 내가 열심히 읽고 공부해 본걸 까먹을 수도 있으니 한 번 글로 남겨 보는게 좋겠다.

앞에서 말한 것 처럼 초기화 작업은 건너 뛰고, userinit()함수와 mpmain()함수가 어떻게 굴러가고 scheduler가 어떻게 작동할 것인지 에 대한 것을 조금 중점적으로 살펴 볼 필요가 있다. 왜냐, 나는 MLFQ 스케줄러를 구현해야 하니까!!


맞다, userinit()은 첫번째로 실행되는 유저 process를 만들어주는 함수이다. 이 함수가 호출이 되면 가장 먼저 allocproc() 함수가 호출된다, allocproc()은 xv6에서 최대로 실행될 수 있는 process의 갯수가 64개인데, 아직 더 process를 실행할 수 있는지 확인하고 만들 수 있다면 proc 구조체와 kernel stack을 할당해주는 역할을 한다. 그리고 할당한 proc을 반환해준다.

<proc.c>

static struct proc*
allocproc(void){

// 64개 돌아보면서 UNUSED 상태인 구조체 찾기
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
    if(p->state == UNUSED)
      goto found;

..

//찾았다면 구조체 초기상태로 할당해주기
found:
  p->state = EMBRYO;
  p->pid = nextpid++;
  p->admin = 0;
  p->lvl = 0;
  p->priority = 0;
  p->tq = ticks;
  p->stsz = 1;

// Allocate kernel stack. (이제 이 아래는 kernel stack을 할당해주는 코드)

..

return p;
}

proc 구조체는 process의 실체를 나타내주는 자료구조이고, kernel stack의 경우에는 process의 상태를 저장해 놓은 자료구조라고 생각하는 것이 좋을 것 같다. 우선 대표적인 구성요소로는 Trapframe과 context가 있다. Trapframe의 경우에는 user-mode에서 kernel-mode로 진입할 때 다시 user-mode로 돌아가기 위해 register들을 저장해 놓은 자료구조이다. Context는 우리가 익히 들어 익숙한 context switching의 그 context 맞다. 현재 process가 일하고 있던 상태(레지스터)를 저장해 놓은 자료구조이다. 구성은 이렇게 되어있다. 구글에서 찾아서 공부하는데 많은 도움이 된 자료였다.

Untitled