jun-wiki

View My GitHub Profile

Posts (Latest 10 updated) :
Read all
Contents:
  1. 준비
    1. 흐름
      1. 1) 부팅 직후 커널 단계 (init.c)
      2. 2) initd 커널 스레드 -> 유저 프로그램 교체
      3. 3) process_exec()
      4. 4) 유저 모드 실행 & 시스템 콜
      5. 5) 종료 경로 & 부모 동기화
      6. 6) 액션 종료 & 전원 끔

ε/̵͇̿̿/’̿’̿ ̿(〒▽〒)

(러시안 룰렛 하는 모습이다)



아쉽게도 살았기에 공부 해야한다

오늘은 argument passing이 목표다

그치만 좀 알아보니 쉽지 않다

구현하고 테스트 돌리려면 몇가지 준비 사항이 필요하니 말이다


준비

일단 시스템 콜 등이 구현안되어 있어 문제다

어디부터 무얼 해야하며 왜 필요한지 알아보겠다

GitBOOK에서는 process_exec부터 구현하라 했는데

이를 구현해봤자 동작은 하지 못한다

이게 로직이 틀리고 맞고를 떠나서 빌드하고 실행이 정상적으로 안되는게 문제다

  • 왜 안되는가?

    모른다

    흐름 정리하고 다시 해봐야겠다

흐름

1) 부팅 직후 커널 단계 (init.c)

  1. main()

    • bss_init(), read_command_line(), parse_options()

    • 스케줄러/인터럽트/타이머 초기화 → thread_start()Boot complete 출력

    • run_actions(argv) 실행
      여기에서 입력 들어온다 (예: -q -f run 'prog args…')

    • -f면 포맷 -p면 파일 올리는 등 수행


2) initd 커널 스레드 -> 유저 프로그램 교체

  1. process_create_initd(task)

    • thread_create("initd", ..., initd, task_string_copy)
  2. initd(void *f_name)

    • process_exec(f_name) 호출 -> 현재 스레드를 “유저 프로세스”로 전환

3) process_exec()

구현 핵심

  1. process_exec(void *f_name)

    • f_name토큰화 -> prog + argv[]
      구현사항

    • process_cleanup()으로 기존 주소공간 제거

    • load(prog, &if_)
      ELF 로드, 코드/데이터 매핑, setup_stack(&if_)로 빈스택 만들기

    • Argunment Passing 구현사항

      • 문자열 유저 스택에 복사 (\0포함, 역순)

      • 8바이트 정렬, argv[argc]는 NULL 센티널

      • argv[i] 포인터 배열 push, 가짜 리턴주소 0 push

      • if_.R.rdi=argc, if_.R.rsi=argv 세팅

    • do_iret(&if_)
      → 사용자 모드 진입 (rip = ehdr.e_entry)
      _start → main(argc, argv) 실행


4) 유저 모드 실행 & 시스템 콜

  1. 유저 프로그램 main(argc, argv)

    • printf/write/exit 등 호출
      → 라이브러리 래퍼가 syscall 명령 실행
  2. 하드웨어/스텁/핸들러

    • CPU가 MSR_LSTAR의 syscall_entry(어셈블리)로 진입
      → 레지스터 저장/커널스택 전환
      syscall_handler(struct intr_frame *f) 호출

    • syscall_handler 디스패처
      (구현사항)

      • SYS_EXIT: status=f->R.rdi 저장 후 thread_exit()

      • SYS_WRITE: fd==1이면 콘솔 putbuf, f->R.rax=written

    • 반환값 존재하는 콜의 경우 f->R.rax에 리턴값 채워 스텁이 sysretq로 유저 복귀

스텁이 뭐냐?
커널 진입/복귀용 어셈블리 연결 코드

  • 스텁 역할:
1. CPU가 `syscall`로 들어오면 **MSR_LSTAR**가 가리키는 이 스텁으로 점프

2. 유저 레지스터 상태를 **struct intr_frame** 에 저장하고, <br>
**커널 스택으로 전환**

3. **C 함수** `syscall_handler(struct intr_frame*)` 호출

4. (리턴 시) 레지스터 복구하고 **`sysretq`** 로 유저로 돌아감

    - 단, `exit`처럼 끝나면 여기로 안 돌아옴

5) 종료 경로 & 부모 동기화

  1. 종료

    • exit(status)
      syscall_handler 에서 thread_exit()
      process_exit()

    • 종료 메시지 (구현 사항)
      printf("%s: exit(%d)\n", cur->name, cur->exit_status);

    • 열린 파일/메모리 해제, 실행 파일 write 허용, 페이지테이블 파기

  2. 부모 측

    • run_task()process_wait(child_tid) 로 대기

    • process_wait() 구현 사항

      • 자식 종료까지 블록, 종료 코드 반환, 중복 wait 방지, 관계 검증

6) 액션 종료 & 전원 끔

  1. run_actions()가 남은 액션 처리 후 종료

    • -qpower_off() 호출, 아니면 thread_exit()로 커널 종료