ε/̵͇̿̿/’̿’̿ ̿(〒▽〒)
(러시안 룰렛 하는 모습이다)
…
아쉽게도 살았기에 공부 해야한다
오늘은 argument passing이 목표다
그치만 좀 알아보니 쉽지 않다
구현하고 테스트 돌리려면 몇가지 준비 사항이 필요하니 말이다
일단 시스템 콜 등이 구현안되어 있어 문제다
어디부터 무얼 해야하며 왜 필요한지 알아보겠다
GitBOOK에서는 process_exec
부터 구현하라 했는데
이를 구현해봤자 동작은 하지 못한다
이게 로직이 틀리고 맞고를 떠나서 빌드하고 실행이 정상적으로 안되는게 문제다
왜 안되는가?
모른다
흐름 정리하고 다시 해봐야겠다
main()
bss_init()
, read_command_line()
, parse_options()
스케줄러/인터럽트/타이머 초기화 → thread_start()
→ Boot complete
출력
run_actions(argv)
실행
여기에서 입력 들어온다 (예: -q -f run 'prog args…'
)
-f
면 포맷 -p
면 파일 올리는 등 수행
process_create_initd(task)
thread_create("initd", ..., initd, task_string_copy)
initd(void *f_name)
process_exec(f_name)
호출 -> 현재 스레드를 “유저 프로세스”로 전환process_exec()
구현 핵심
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)
실행
유저 프로그램 main(argc, argv)
printf
/write
/exit
등 호출 syscall
명령 실행하드웨어/스텁/핸들러
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`처럼 끝나면 여기로 안 돌아옴
종료
exit(status)
→ syscall_handler
에서 thread_exit()
→ process_exit()
종료 메시지 (구현 사항)
printf("%s: exit(%d)\n", cur->name, cur->exit_status);
열린 파일/메모리 해제, 실행 파일 write 허용, 페이지테이블 파기
부모 측
run_task()
가 process_wait(child_tid)
로 대기
process_wait()
구현 사항
run_actions()
가 남은 액션 처리 후 종료
-q
면 power_off()
호출, 아니면 thread_exit()
로 커널 종료