[SW정글 55일차] PintOS 시작점 init.c

rg.log·2022년 11월 12일
2

SW 사관학교 JUNGLE

목록 보기
12/31

대망의 PintOS가 시작되었다.

PintOS 흐름

threads > init.c 의 main 함수 호출

순차적으로 부팅에 필요한 초기화 함수가 진행된다.

  1. BSS를 지우고 머신의 RAM size를 가져온다
    a. BSS 지우기 ( BSS는 0으로 초기화되어야 하는 세그먼트. 실제로 디스크에 저장되거나 커널에 의해 0이되지 않음. 직접 0으로 만들어야함) (BSS의 시작은 _start_bss. 끝은 _end_bss로 기록됨)

  2. 명령줄을 인수로 구분하고 옵션을 구문 분석한다.

  3. lock을 사용할 수 있도록 스레드로 초기화. 그런 다음 콘솔 잠금 사용.
    a. thread_init()
    b. console_init()

  4. 메모리 시스템 초기화
    a. 페이지 테이블을 커널 가상 매핑으로 채운 후 새 페이지 디렉토리를 사용하도록 CPU를 설정한다. (base_pml4는 생성된 pml4를 가리킴)

    • pml4 : 페이지 맵 레벨4

    실제 주소 [0 ~ mem_end]를 [LOADER_KERN_BASE ~ LOADER_KERN_BASE + mem_end]에 매핑

  5. 인터럽트 핸들러 초기화

    • 인터럽트 핸들러 : 인터럽트 발생시 이를 핸들링하기 위해 호출되는 함수
  6. 쓰레드 스케줄러와 인터럽트 활성화 시작
    a. thread_start() 함수를 통해 인터럽트를 활성화하여 쓰레드 선점 스케줄링(preemptive thread scheduling)을 시작하고 유휴 쓰레드를 만든다.

    • 선점 스케줄링(preemptive scheduling)은 인터럽트나 시스템 호출 종료 시에 더 높은 우선 순위 프로세스가 발생되었음을 알았을 때, 현 실행 프로세스로부터 강제로 CPU를 회수하는 것
  7. 파일 시스템 초기화

  8. 커널의 명령줄에서 지정된 actions 실행함
    a. run_actions 함수를 통해 응용 프로그램을 실행한다던가 thread를 테스트한다던가 하는 각 task 별로 평가가 진행된다.

  9. 끝낸다.
    a. PintOS가 실행되는 가상머신인 Bochs 또는 QEMU에서 실행 중인 시스템의 전원을 끈다.

세부 기본 코드

thread.c 의 idle

유휴 쓰레드(idle thread) : 실행할 준비가 된 다른 쓰레드가 없을 때 실행된다.
유휴 쓰레드는 처음에 idle_thread를 초기화할 때 한 번 thread_start() 함수에 의해 ready list에 배치된다. ready list가 비어있는 상황을 하나하나 처리하는 대신 idle_thread를 넣어둔다. 일부 악명 높은 예외를 제외하고 idle_thread가 다른 쓰레드를 실행할 수 있도록 할 때까지 시스템을 저전력 상태로 둔다.

/* 가장 낮은 우선순위로 idle 쓰레드를 생성 */
thread_create ("idle", PRI_MIN, idle, &idle_started);

/* 커널 스레드의 기본으로 사용되는 함수 */
static void
kernel_thread (thread_func *function, void *aux) {
	ASSERT (function != NULL);

	intr_enable ();       /* 스케줄러가 인터럽트를 끈 상태에서 실행. */
	function (aux);       /* 스레드 함수 실행. */
	thread_exit ();       /* 함수가 반환되면 thread kill */
}

/* 유휴 스레드.
   실행할 준비가 된 다른 스레드가 없을 때 실행.
   유휴 스레드는 처음에 thread_start()에 의해 준비 목록에 표시.
   처음에 한 번 예약되며, 이 시점에서 idle_thread를 초기화하고
	thread_start()가 계속될 수 있도록 전달된 세마포를 "업"한 후 즉시 차단.

	그 후 유휴 스레드는 준비 목록에 나타나지 않음.
	준비 목록이 비어 있는 경우 next_thread_to_run()에서 특별한 경우로 반환 */
static void
idle (void *idle_started_ UNUSED) {
	struct semaphore *idle_started = idle_started_;

	idle_thread = thread_current ();
	sema_up (idle_started);

	for (;;) {
		/* Let someone else run. */
		intr_disable ();
		thread_block ();
		asm volatile ("sti; hlt" : : : "memory");
	}
}

assert 함수

디버깅 모드에서 개발자가 오류가 생기면 치명적일 것이라는 곳에 심어놓은 에러 검출용 코드이다.

#define ASSERT(CONDITION)                                      
	if ((CONDITION)) { } else {                             
		PANIC ("assertion `%s' failed.", #CONDITION);   
	}
    
/* Halts the OS, printing the source file name, line number, and
 * function name, plus a user-specific message. */
#define PANIC(...) debug_panic (__FILE__, __LINE__, __func__, __VA_ARGS__)

ASSERT (intr_get_level () == INTR_OFF);

해당 CONDITION이 아니면 OS를 중지하고 원본 파일 이름, 줄 번호 및 기능 이름과 사용자별 메시지를 출력한다.

참고.
인터럽트 핸들러
선점 스케줄링
Idle Thread
시스템 유휴 프로세스


오늘의 나는

ktx 타고 대전으로 돌아오는 한 시간 안에 복습 차원의 데일리 블로깅을 끝내자 했는데 쉽지 않다. 정리를 잘하는 사람들은 많은 시간을 투자하는 걸까. 참 대단하고 감사하다. 🫶🏻

비 오는 문지 캠퍼스는 처음인데 운치 있다. 네이버 지도를 믿고 안 가던 길로 가다가 허탕치고 돌아돌아 오게 된 정문 길이었는데 오히려 좋았다. 서울에 있다 와서 그런지 길이 넓고 조용하니 조경이 정리돼있는 게 해외에 온 거 같아 좋았다.

머리를 싹둑 잘랐다. 동갑내기 미용사도 어색할거다 괜찮냐 물어보는데 너무 개운하다. 긴머리의 효율을 못느껴 진즉에 자를 걸이라는 생각밖에 안 들었다.

1개의 댓글

comment-user-thumbnail
2022년 11월 30일

좋은 글이네요! 잘 보고 가요!

답글 달기