Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- defee
- 백준
- 리액트
- 나만무
- corou
- 시스템콜
- 오블완
- JavaScript
- 코드트리
- TiL
- 모션비트
- 크래프톤 정글
- 핀토스
- 소켓
- Vue.js
- 4기
- 자바
- CSS
- 사이드프로젝트
- userprog
- 알고리즘
- 티스토리챌린지
- 크래프톤정글
- HTML
- pintos
- Java
- Flutter
- 자바스크립트
- 스택
- 큐
Archives
- Today
- Total
미새문지
크래프톤 정글 week08, day66 - userprog 뜯기 본문
728x90
계속 쉬운것만 잔디를 심다보니 최근에는 올리지 않는게 더 나을 것 같아 pintos가 끝날 동안엔 잔디심기를 안 올릴 것 같다.
%rdi | 주로 첫 번째 인자 전달에 사용되며, 문자열이나 배열 같은 데이터의 목적지 주소를 지정하는데 사용된다. |
%rsi | 두 번째 인자 전달에 사용되며, 문자열이나 배열같은 데이터의 원본 주소를 지정하는데 사용된다. |
%rdx | 세 번째 인자 전달에 사용되며, 입출력 관련 시스템 호출에서 파일 디스크립터나 버퍼의 크기 등을 전달하는데에도 활용된다. |
%rcx | 네 번째 인자 전달에 사용되며, 반복(loop) 카운트를 관리하는데에 사용될 수 있다. 또한 몇 명령어에서는 반복 횟수를 지정하는데 사용된다. |
%r8 | 다섯 번째 인자 전달에 사용되며, x86-64 아키텍쳐에서 새롭게 추가된 레지스터 중 하나로, 추가적인 인자를 전달하는데 사용된다. |
%r9 | 여섯 번째 인자 전달에 사용되며, %r8과 마찬가지로, x86-64 아키텍쳐에서 추가된 레지스터로, 더 많은 인자를 함수에 전달한다. |
x86-64 RET | return의 약자이며 함수 호출 완료 후, 제어 반환한다. 수행작업은 스택 포인터로 반환된 주소 가져오기, 프로그램 카운터를 업데이트하여, 해당 주소의 명령어로 실행 흐름을 이동하는 작업이 있다. |
userprog의 기본적인 시작은 init.c의 메인에서 시작한다.
/* Pintos main program. */
int
main (void) {
uint64_t mem_end;
char **argv;
/* Clear BSS and get machine's RAM size. */
bss_init ();
/* Break command line into arguments and parse options. */
argv = read_command_line ();
argv = parse_options (argv);
/* Initialize ourselves as a thread so we can use locks,
then enable console locking. */
thread_init ();
console_init ();
/* Initialize memory system. */
mem_end = palloc_init ();
malloc_init ();
paging_init (mem_end);
#ifdef USERPROG
tss_init ();
gdt_init ();
#endif
/* Initialize interrupt handlers. */
intr_init ();
timer_init ();
kbd_init ();
input_init ();
#ifdef USERPROG
exception_init ();
syscall_init ();
#endif
/* Start thread scheduler and enable interrupts. */
thread_start ();
serial_init_queue ();
timer_calibrate ();
#ifdef FILESYS
/* Initialize file system. */
disk_init ();
filesys_init (format_filesys);
#endif
#ifdef VM
vm_init ();
#endif
printf ("Boot complete.\n");
/* Run actions specified on kernel command line. */
run_actions (argv);
/* Finish up. */
if (power_off_when_done)
power_off ();
thread_exit ();
}
우리는 터미널에 작성한 명령어를 뜯어봐야 하기 때문에 커맨드 라인의 작업을 실행하는 run_actions로 진입
/* ARGV[]에 지정된 모든 액션을 널 포인터 센티널까지 실행합니다. */
static void
run_actions (char **argv) {
/* An action. */
struct action {
char *name; /* 작업 이름 */
int argc; /* # 액션 이름을 포함한 인수 개수입니다. */
void (*function) (char **argv); /* 액션을 실행하는 함수입니다. */
};
/* 지원되는 작업 표입니다. */
static const struct action actions[] = {
{"run", 2, run_task},
#ifdef FILESYS
{"ls", 1, fsutil_ls},
{"cat", 2, fsutil_cat},
{"rm", 2, fsutil_rm},
{"put", 2, fsutil_put},
{"get", 2, fsutil_get},
#endif
{NULL, 0, NULL},
};
while (*argv != NULL) {
const struct action *a;
int i;
/* 작업 이름 찾기. */
for (a = actions; ; a++)
if (a->name == NULL)
PANIC ("unknown action `%s' (use -h for help)", *argv);
else if (!strcmp (*argv, a->name))
break;
/* 필수 인수가 있는지 확인합니다. */
for (i = 1; i < a->argc; i++)
if (argv[i] == NULL)
PANIC ("action `%s' requires %d argument(s)", *argv, a->argc - 1);
/* 작업을 호출하고 진행합니다. */
a->function (argv);
argv += a->argc;
}
}
작업을 실행시켜야 하기 때문에 {"run", 2, run_task}로 진입한다.
/* ARGV[1]에 지정된 작업을 실행합니다. */
static void
run_task (char **argv) {
const char *task = argv[1];
printf ("Executing '%s':\n", task);
printf ("end\n");
#ifdef USERPROG
if (thread_tests){
run_test (task);
} else {
process_wait (process_create_initd (task));
}
#else
run_test (task);
#endif
printf ("Execution of '%s' complete.\n", task);
}
커맨드라인에 입력한 명령어를 각각 쪼개서 인자로 받는데 args[1]은 두 번째 명령어를 뜻한다.
thread_tests가 true라면 특정 테스트를 실행하고, false라면 프로세스 생성하고 실행에 들어간다.
process_wait의 process_create_initd로 진입한다.
/* FILE_NAME에서 로드된 "initd"라는 첫 번째 유저랜드 프로그램을 시작합니다.
process_create_initd()가 반환되기 전에 새 스레드가 예약될 수 있으며 종료될 수도 있습니다.
initd의 스레드 ID를 반환하거나, 스레드를 생성할 수 없는 경우 TID_ERROR를 반환합니다.
이 함수는 한 번만 호출해야 한다는 점에 유의하세요. */
tid_t
process_create_initd (const char *file_name) {
char *fn_copy;
tid_t tid;
/* FILE_NAME의 복사본을 만듭니다.
* 그렇지 않으면 호출자와 load() 사이에 경합이 발생합니다. */
fn_copy = palloc_get_page (0);
if (fn_copy == NULL)
return TID_ERROR;
strlcpy (fn_copy, file_name, PGSIZE);
/* 새 스레드를 생성하여 FILE_NAME을 실행합니다. */
tid = thread_create (file_name, PRI_DEFAULT, initd, fn_copy);
if (tid == TID_ERROR)
palloc_free_page (fn_copy);
return tid;
}
file_name을 인자로 받아 fn_copy에 복사본을 만들고 스레드를 생성하여 file_name을 실행하기 때문에 initd로 진입
/* 첫 번째 사용자 프로세스를 시작하는 스레드 함수입니다. */
static void
initd (void *f_name) {
#ifdef VM
supplemental_page_table_init (&thread_current ()->spt);
#endif
process_init ();
if (process_exec (f_name) < 0)
PANIC("Fail to launch initd\n");
NOT_REACHED ();
}
VM은 project3쪽이라 아직 볼 필요가 없다. 프로세스를 생성하고 생성이 실패했으면 PANIC에 걸려 종료된다. 확인하기 위해 exec로 진입한다.
/* 현재 실행 컨텍스트를 f_name으로 전환합니다. 실패하면 -1을 반환합니다. */
int
process_exec (void *f_name) {
char *file_name = f_name;
bool success;
// 현재 스레드 받아오기
struct thread *cur_thread = thread_current();
/* 스레드 구조에서는 intr_frame을 사용할 수 없습니다.
현재 스레드가 스케줄을 변경할 때 실행 정보를 멤버에 저장하기 때문입니다. */
struct intr_frame _if;
_if.ds = _if.es = _if.ss = SEL_UDSEG;
_if.cs = SEL_UCSEG;
_if.eflags = FLAG_IF | FLAG_MBS;
// 토큰 선언
char *token, *save_ptr;
/* 먼저 현재 컨텍스트를 죽입니다. */
process_cleanup ();
// 명령줄 인자 배열
char *argv[10];
// 인자 개수
int *argc;
// 인자 셀거
int i = 0;
for (token = strtok_r (file_name, " ", &save_ptr); token != NULL && i < 10;
token = strtok_r (NULL, " ", &save_ptr)) {
argv[i] = token;
// printf("'%s'\n", token);
i++;
}
argc = i; // 인자 개수 설정
printf("%s\n", token);
/* 그런 다음 바이너리를 로드합니다. */
success = load (file_name, &_if);
/* 로드에 실패하면 종료합니다. */
palloc_free_page (file_name);
if (!success)
return -1;
/* 전환된 프로세스를 시작합니다. */
do_iret (&_if);
NOT_REACHED ();
}
exec에서 인자를 받아와 저장 후 스택에 넣어줘야 하는데 그 부분은 아직 코드 작성 중이다. token 변수를 사용해서 인자들을 받아왔지만 스택 코드를 어떻게 작성해야 하는지 몰라서 막혔다.
어제 TIL을 못써서 오늘 아침에 작성했기 때문에 다 쓰고 다시 코드 작성 진행하려고 한다.
학습 시간 : 10 ~ 26시
728x90
'크래프톤 정글 > TIL' 카테고리의 다른 글
크래프톤 정글 week09, day68 - 시스템 콜 구현 막혀있는 중 (2) | 2024.03.16 |
---|---|
크래프톤 정글 week09, day67 - 시스템 콜 함수 간단정리 (1) | 2024.03.15 |
크래프톤 정글 week08, day65 - Atomic Operation, Rax Register, Cache (1) | 2024.03.12 |
크래프톤 정글 week08, day64 - "User Mode vs Kernel Mode", "Register vs Memory", User Stack, 잔디심기 (1) | 2024.03.11 |
크래프톤 정글 week08, day63 - 잔디심기, pintOS - Project1 result (1) | 2024.03.11 |