xv6는 MIT에서 교육 목적으로 만든 미니 운영체제입니다. Unix V6를 현대적으로 재구현한 것으로, 약 1만 줄의 C 코드로 OS의 핵심 개념을 모두 담고 있습니다.


xv6란

MIT 6.S081(Operating System Engineering) 강의를 위해 만든 교육용 운영체제 입니다.

  • Unix V6 (1975년)의 현대적 재구현
  • RISC-V 아키텍처 기반 (xv6-riscv)
  • 약 1만 줄의 C + 어셈블리 코드
  • 멀티프로세서 지원, 가상 메모리, 파일 시스템 포함

xv6의 구조

PLAINTEXT
┌──────────────────────────────────┐
│  사용자 프로그램 (sh, ls, cat 등)  │
├──────────────────────────────────┤
│  시스템 콜 인터페이스               │
│  (fork, exec, read, write 등)    │
├──────────────────────────────────┤
│  커널                            │
│  ┌────────┬──────┬────────────┐ │
│  │ 프로세스 │ 메모리│ 파일 시스템  │ │
│  │ 관리    │ 관리 │            │ │
│  ├────────┼──────┼────────────┤ │
│  │ 트랩/   │ 디바이│ 디스크      │ │
│  │ 인터럽트│ 스    │ 드라이버    │ │
│  └────────┴──────┴────────────┘ │
├──────────────────────────────────┤
│  하드웨어 (RISC-V, QEMU 에뮬레이션) │
└──────────────────────────────────┘

핵심 구현 살펴보기

1. 프로세스 관리

C
// kernel/proc.h
struct proc {
    struct spinlock lock;
    enum procstate state;     // UNUSED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE
    int pid;
    struct proc *parent;
    void *kstack;             // 커널 스택
    uint64 sz;                // 프로세스 메모리 크기
    pagetable_t pagetable;    // 페이지 테이블
    struct trapframe *trapframe;  // 트랩 시 레지스터 저장
    struct file *ofile[NOFILE];   // 열린 파일
    struct inode *cwd;            // 현재 디렉토리
    char name[16];
};

2. 시스템 콜

C
// kernel/syscall.c
// 트랩 발생 → syscall() 호출 → 시스템 콜 번호로 분기
void syscall(void) {
    int num;
    struct proc *p = myproc();

    num = p->trapframe->a7;   // a7 레지스터에 시스템 콜 번호

    if (num > 0 && num < NELEM(syscalls) && syscalls[num]) {
        p->trapframe->a0 = syscalls[num]();  // 시스템 콜 실행, 결과를 a0에
    } else {
        printf("unknown sys call %d\n", num);
        p->trapframe->a0 = -1;
    }
}

3. 스케줄러

C
// kernel/proc.c
// 라운드 로빈 스케줄러
void scheduler(void) {
    struct proc *p;
    struct cpu *c = mycpu();

    for (;;) {
        // 프로세스 테이블을 순회하며 RUNNABLE 프로세스를 찾음
        for (p = proc; p < &proc[NPROC]; p++) {
            acquire(&p->lock);
            if (p->state == RUNNABLE) {
                p->state = RUNNING;
                c->proc = p;
                swtch(&c->context, &p->context);  // 컨텍스트 스위칭
                c->proc = 0;
            }
            release(&p->lock);
        }
    }
}

4. 가상 메모리 (페이지 테이블)

xv6는 RISC-V의 Sv39 페이지 테이블 (3단계, 39비트 가상 주소)을 사용합니다.

C
// kernel/vm.c
// 가상 주소를 물리 주소로 매핑
int mappages(pagetable_t pagetable, uint64 va, uint64 size,
             uint64 pa, int perm) {
    // 3단계 페이지 테이블 워크
    // PTE 설정: 물리 주소 + 권한 비트
}

5. 파일 시스템

PLAINTEXT
xv6 파일 시스템 구조:
┌────────┬────────┬────────┬────────┬───────────────┐
│ Boot   │ Super  │ Log    │ Inode  │ Data Blocks   │
│ Block  │ Block  │ Blocks │ Blocks │               │
└────────┴────────┴────────┴────────┴───────────────┘

- 저널링(log) 지원으로 크래시 복구
- inode 기반 파일 관리
- 디렉토리는 특수한 파일 (이름→inode 번호 매핑)

xv6 빌드 및 실행

BASH
# 소스 클론
git clone https://github.com/mit-pdos/xv6-riscv.git
cd xv6-riscv

# 빌드 및 QEMU에서 실행
make qemu

# xv6 셸에서
$ ls
$ echo hello
$ cat README

xv6로 배울 수 있는 것

개념xv6에서의 구현
프로세스 생성fork(), exec()
컨텍스트 스위칭swtch() 함수 (어셈블리)
시스템 콜트랩 핸들러 + syscall()
가상 메모리3단계 페이지 테이블
파일 시스템inode, 디렉토리, 저널링
동기화spinlock, sleep/wakeup
인터럽트PLIC (외부), CLINT (타이머)

핵심 포인트

  • xv6를 공부하는 이유: 실제 OS의 핵심 개념을 간결한 코드로 이해할 수 있음
  • fork()의 내부: 페이지 테이블 복사 + 프로세스 구조체 생성 + RUNNABLE 상태로 설정
  • 컨텍스트 스위칭이 실제로 무엇을 저장하는가: callee-saved 레지스터 + 스택 포인터

정리

xv6는 OS의 핵심을 1만 줄로 응축한 교과서적인 운영체제입니다. 프로세스, 메모리, 파일 시스템, 동기화의 실제 구현을 코드로 확인할 수 있어서, OS 개념을 깊이 이해하고 싶은 개발자에게 최고의 학습 자료입니다.

댓글 로딩 중...