[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