코로나 양성 😱
어쩐지 숨 쉬기가 힘들..
우선 최소 5일은 기숙사 방에 격리하면서 학습
10:10 착석
어제 우선 파일명을 토큰화 하는 것 까지는 함.
이제 토큰화된 정보를 스택에 넣어야 되는 것 같음.
프로그램에 전달된 인자의 수
program arg1 arg2인 경우 argc는 3
(프로그램명도 인자로 간주)
인자들의 실제 값을 포함하는 문자열 배열
char *argv[]
형태의 배열로 저장
argv[0]은 실행 파일 이름
argv[1] 부터는 실제 전달된 인자
argv[argc]는 항상 NULL이며 배열의 끝을 나타냄.
이런 식으로 선언됨.
int main(int argc, char *argv[]) {
// 프로그램 로직
}
이건 스택 포인터를 저장하는 레지스터
RSP는 스택의 마지막 원소를 가리키고 있으며,
스택은 8바이트 단위로 이동함.
대략적인 흐름 아이디어
1. 인자들을 사용자 스택에 복사
2. argv 배열을 스택에 배치
3. argc와 argv를 설정
4. 스택 포인터를 적절하게 초기화
굳이 동적 할당할 필요 없을 거 같아서.. 배열 128개로 바꿈.
char *token;
char *next_ptr;
int argc = 0;
char *argv[128];
token = strtok_r(file_name, " ", &next_ptr);
while (token != NULL && argc < 128) {
argv[argc++] = token;
token = strtok_r(NULL, " ", &next_ptr);
}
pintos --fs-disk=10 -p tests/userprog/args-single:args-single -- -q -f run 'args-single onearg'
이번 과제는 레퍼런스 없이 구현하는 거 무리..
솔루션 보고 이해해보고 다시 구현해 보는 걸로 타협
/* 아큐먼트 파싱 */
char *argv[128];
int argc = 0;
char *token;
char *save_ptr;
token = strtok_r(file_name, " ", &save_ptr);
while (token != NULL && argc < 128) {
argv[argc++] = token;
token = strtok_r(NULL, " ", &save_ptr);
}
시스템콜이 발생하는 건 인터럽트가 발생하는 거다.
그래서 인터럽트 프레임이 필요함.
왜냐면 인터럽트가 끝나고 다시 인터럽트 전으로 돌아가야 하니까.
인터럽트 프레임은 현재 프로세스의 레지스터 상태와 스택 정보를 저장하는 구조체이다.
인터럽트 프레임의 역할을 이해하는데 오래 걸림. 핵심은 이거.
인터럽트가 발생하면 현재 실행 중인 프로세스의 레지스터 상태와 스택 상태를 인터럽트 프레임에 저장한다.
void **rspp = &_if.rsp;
argument_stack(argv, argc, rspp);
_if.R.rdi = argc;
_if.R.rsi = (uint64_t)*rspp + sizeof(void *);
이 코드에서 rdi 레지스터에 인자의 개수를 설정하고,
rsi 레지스터에 두 번째 인자부터 쌓일 스택 포인터를 넘기면 된다.
이건 상식으로 외우기
rdi는 함수의 첫 번째 인자, 보통 argc 값
rsp는 스택 포인터
rsi는 스택 포인터의 다음 포인터(다음 값이 들어갈 위치)