[FLOW CHART] Command Line Parsing - Week9-11-team03/Pintos-User-Program GitHub Wiki
🧵 명령어 인자 파싱 흐름 (Command-Line Parsing Control Flow)
이 문서는 Pintos에서
load()
함수와argument_stack()
함수가 명령어 인자를 어떻게 파싱하고 스택에 적재하는지를 설명합니다. 최종 목적은 실행 파일을 메모리에 적재하고, 유저 스택을 설정한 뒤,main(int argc, char** argv)
형식으로 인자를 넘겨주는 것입니다.
📌 개요
- 입력 예시:
"echo hello world"
라는 문자열이 인자로 들어옴 - 목표:
"echo"
실행 파일을 로드하고, 아래와 같은 형식으로 인자 전달main(int argc = 3, char **argv = ["echo", "hello", "world"])
🔁 전체 흐름도 (텍스트 기반 플로우 차트)
시작
│
├─▶ strtok_r()로 file_name을 공백 기준 분리
│ └─ 결과: arg_list = ["echo", "hello", "world"]
│
├─▶ 실행 파일 열기: filesys_open(arg_list[0])
│ └─ 실패 시 false 반환
│
├─▶ ELF 헤더 읽기: file_read()
│ └─ 매직 넘버 등 확인 → 실패 시 false 반환
│
├─▶ 모든 program header에 대해 반복:
│ └─ load_segment()로 메모리에 적재
│
├─▶ 스택 초기화: setup_stack(if_)
│ └─ 빈 스택 생성 (rsp = PHYS_BASE)
│
├─▶ argument_stack(arg_list, argc, if_) 호출
│ ├─ 문자열을 스택에 역순으로 복사
│ ├─ 8바이트 단위로 정렬
│ ├─ NULL (argv[argc]) 삽입
│ ├─ 각 문자열 주소 포인터 삽입
│ ├─ argv 배열의 시작 주소 삽입
│ ├─ argc 삽입
│ └─ 가짜 리턴 주소(0) 삽입
│
├─▶ 레지스터 설정
│ ├─ rdi ← argc
│ └─ rsi ← argv (포인터)
│
└─▶ 프로그램 시작 위치로 점프 (rip ← entry point)
└─ 성공 시 true 반환
스택 구조 예시 (argument_stack() 호출 이후)
[낮은 주소]
┌────────────────────────────┐
│ "world\0" 문자열 │ ← arg_list[2]
├────────────────────────────┤
│ "hello\0" 문자열 │ ← arg_list[1]
├────────────────────────────┤
│ "echo\0" 문자열 │ ← arg_list[0]
├────────────────────────────┤
│ 정렬용 패딩 (0~7바이트) │
├────────────────────────────┤
│ NULL 포인터 (argv[argc]) │
├────────────────────────────┤
│ argv[2] → "world" 주소 │
│ argv[1] → "hello" 주소 │
│ argv[0] → "echo" 주소 │
├────────────────────────────┤
│ argc = 3 │
├────────────────────────────┤
│ 리턴 주소 (0) │
└────────────────────────────┘
[높은 주소]
💡 핵심 정리
역할 | 함수 | 설명 |
---|---|---|
ELF 실행 파일 열기 | load() | 실행 파일을 열고 메모리에 적재 |
인자 분리 및 스택 설정 | argument_stack() | 인자를 문자열 형태로 복사 후 포인터 배열 구성 |
스택 포인터, 인자 개수 설정 | 레지스터 설정 | rdi = argc, rsi = argv |