| 일 | 월 | 화 | 수 | 목 | 금 | 토 | 
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 | 
| 12 | 13 | 14 | 15 | 16 | 17 | 18 | 
| 19 | 20 | 21 | 22 | 23 | 24 | 25 | 
| 26 | 27 | 28 | 29 | 30 | 31 | 
- pintos
- 파스칼삼각형
- 개발자
- 상대 엔트로피
- qq플롯
- 군간
- Java
- 알고리즘
- 행렬
- 앱개발
- Android
- 선형대수학
- AIC
- 잔차
- 자바
- 군내
- f비
- ios
- 비둘기집원리
- 앱
- 평균로그우도
- Flutter
- 일반화오차
- 논리회로 #컴퓨터
- 개발
- 운영체제
- 최대우도법
- 조건부정리
- Eigenvector
- Eigenvalue
- Today
- Total
Dev_bob
[PintOs] Argument Passing 주요 개념 정리 본문
과제 내용
✅ 변경 전
기존의 pintOs 코드에서 process_execute(”echo x y z”)를 호출하면,
Thread name으로 “echo x y z” 문자열이 통째로 사용된다.
그렇게되면, “echo x y z”라는 문자열을 찾게되는데, 이는 당연히 실패하게 된다.
또한 argv, argc 또 한 전달 되지 않는다.
✅ 변경 후
똑같은 호출 process_execute(”echo x y z”) 이지만, 내부적으로는
Thread name : "echo" 첫 토큰만 사용
파일탐색 : "echo" 이라는 실행파일 찾음
Argument passing : "echo", "x", "y", "z" 를 스택에 복사, argc =4, argv[ ]를 구성하여 사용자 프로그램으로 전달
int main(int argc, char *argv[]) {...그렇게 되면, 사용자 코드가 정상적인 인자를 전달 받을 수 있게 된다.
주요 개념
process_exec()에서 하는일
1. f_name을 tokenizing
“echo x y z”=>echo", "x", "y", "z
2. load()를 하여 ELF파일 로딩
파일시스템의 실행파일인 ELF 파일을 열어서 ELF파일의 코드와 데이터를 User의 Virtual memory에 복사한다.
3. setup_stack()으로 유저가 사용할 스택을 생성
User Virtual Memory의 맨 위쪽, 4KB 공간의 가장 끝(=가상주소의 제일 높은쪽)에서 아래방향으로 쌓이게 됨.
4. do_iret
Ring 0(커널모드) -> Ring1 (유저모드)로 전환
5. 유저프로그램 실행 시작
USER STACK 채우기
USER STACK은 주소가 위->아래로 작아지는 방향으로 스택이 push된다.
주어진 문자열 : %bin/ls –l foo bar

스택의 높은주소로부터 낮은주소로 쌓이는 요소들에 대해 나열해보겠다.
그전에 알아둬야 하는 개념은, 스택은 높은 주소->낮은주소로 쌓이고, 실제 실행시 코드는 낮은주소->높은주소로 읽는다.
1. 문자열, 실제 값들
"%bin/ls" "–l" "foo" "bar"
로 tokenizing 된 token에 대해서 stack은 오른쪽에서 왼쪽방향 순서로 스택에 넣는다.
즉 "bar"~ "%bin/ls" 순으로 넣는것인데, 이는 나중에 code가 stack 값을 읽을때에는 낮은주소에서 높은주소 방향으로 읽기 때문이다.
그래야 바른 순서로 읽힌다.
2. word align padding
8바이트 정렬을 맞추기 위해 padding하는 과정이 들어가게된다.
그 이유는 cpu가 데이터를 8바이트 단위로 정렬된 상태로 읽을때 성능이 좋기 때문이다.
즉 위에서 문자열 실제 값들을 복사한 후에 argv[ ] 배열을 push 하기 전 스택포인터인 rsp를 8의 배수로 맞추는 padding작업을 한다.
padding이란, 정렬을 맞추거나 공간을 채우기 위해 의미 없는 데이터를 메모리에 추가해놓는 것이다.
3. argv[argc] : NULL포인터 삽입
argv[] 배열의 끝을 명시하기 위해 NULL포인터를 argv[argc]로 초기화하여 스택에 push한다.
4. argv[] 배열 시작주소
5. argc 값
argument 개수
6. Fake return address
main함수가 끝나면 return 함수를 0으로 줌으로써 프로그램이 종료되게 끔 함.
이렇게되면, 실제로 실행될때에는
return address -> argc -> argv[] 배열 시작주소 -> word align padding - > 문자열 실제 값 
순으로 실행된다. 
int main(int argc, char *argv[]) {...
_if , 인터럽트 프레임이란?
Interrupt frame이란 CPU 레지스터 상태를 저장해놓은 구조체이다.
user program을 실행하거나 되돌릴 때 사용된다.(Context save)
인터럽트 프레임의 레지스터 의미
| RIP | 다음에 실행할 명령어 주소 | 
| RSP | 스택 포인터 | 
| RDI, RSI, RAX, ... | 함수 인자, 계산 중간값 등 | 
| RFLAGS | 플래그 (인터럽트 허용 여부 등) | 
| CS, SS | 코드/스택 세그먼트 (권한 레벨 포함) | 
인터럽트 프레임은 커널 스택에 위치한다.
ABI (컴파일된 프로그램이 OS와 CPU에서 실행될 수 있도록 정한 규약)에 따라,
RDI <- argc
RSI <- argv
...
으로 레지스터 값에 저장된다.
'프로젝트 > pintOs' 카테고리의 다른 글
| [pintOs]Process Termination Message (2) | 2025.06.02 | 
|---|