운영체제(OS)/with PintOS

(Project2-User Programs) - Argument Passing

스탠딩 2023. 12. 26. 21:18

Argument Passing

process_exec()에서 사용자 프로그램에 대한 인수를 설정하세요.

Implement the argument passing.

현재 process_exec()은 새 프로세스에 대한 인수 전달을 지원하지 않습니다. 이 기능을 구현하려면 process_exec()을 확장하여 단순히 프로그램 파일 이름을 인수로 받는 대신 공백으로 단어로 나누도록 합니다. 첫 번째 단어는 프로그램 이름, 두 번째 단어는 첫 번째 인수가 되는 식으로 말이죠. 즉, process_exec("grep foo bar")는 두 개의 인자 foo와 bar를 전달하여 grep을 실행해야 합니다.


명령줄 내에서 여러 개의 공백은 하나의 공백에 해당하므로 process_exec("grep foo bar")는 원래 예제와 동일합니다. 명령줄 인수의 길이에 합리적인 제한을 둘 수 있습니다. 예를 들어 인수를 한 페이지(4KB)에 들어갈 수 있는 길이로 제한할 수 있습니다. (pintos 유틸리티가 커널에 전달할 수 있는 명령줄 인수는 128바이트로 제한되어 있습니다.)


인자 문자열은 원하는 방식으로 파싱할 수 있습니다. 길을 잃었다면 include/lib/string.h에 프로토타입이 있고 lib/string.c에 철저한 주석으로 구현된 strtok_r()을 참조하세요. 자세한 내용은 man 페이지(프롬프트에서 man strtok_r 실행)에서 확인할 수 있습니다.

int process_exec(void *f_name)
{
    char *file_name = f_name;
    bool success;

    /* We cannot use the intr_frame in the thread structure.
     * This is because when current thread rescheduled,
     * it stores the execution information to the member. */
    struct intr_frame _if;
    _if.ds = _if.es = _if.ss = SEL_UDSEG;
    _if.cs = SEL_UCSEG;
    _if.eflags = FLAG_IF | FLAG_MBS;

    int argc = 0;
    char *argv[128] = {0}; // 이중 리스트
    char *tmp;
    char *token = strtok_r(file_name, " ", &tmp);
    while (token != NULL)
    {
        argv[argc] = token;
        argc++;
        token = strtok_r(NULL, " ", &tmp); // 파싱해서
    }
    argv[argc] = NULL;

    /* We first kill the current context */
    process_cleanup();
    /* And then load the binary */
    success = load((char *)argv[0], &_if); // 패싱

    if (success)
    {
        thread_current()->process_load = true;
        argument_stack(argv, argc, (uintptr_t *)(&(_if.rsp)));
        set_arg_reg(&_if, argc, argv[0]);
    }

    /* If load failed, quit. */
    palloc_free_page(file_name);
    if (!success)
        return -1;

    /* Start switched process. */
    do_iret(&_if);
    NOT_REACHED();
}