Shell: 두 판 사이의 차이

youngwiki
편집 요약 없음
편집 요약 없음
11번째 줄: 11번째 줄:
<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
int main() {
int main() {
     char cmdline[MAXLINE]; /* command line */
     char cmdline[MAXLINE]; /* 명령어를 입력받을 버퍼이다. */
     while (1) {
     while (1) {
         /* read */
         /* read */
         printf("> ");
         printf("> ");
         Fgets(cmdline, MAXLINE, stdin);
         Fgets(cmdline, MAXLINE, stdin); /* 명령어를 입력받는다. */
         if (feof(stdin))
         if (feof(stdin))
             exit(0);
             exit(0);
          
          
         /* evaluate */
         /* evaluate */
         eval(cmdline);
         eval(cmdline); /* 명령어를 실행시킨다 */
     }
     }
}
}
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
void eval(char *cmdline) {
void eval(char *cmdline) { /* cmdline은 사용자가 입력한 명령어 문자열이다. */
     char *argv[MAXARGS]; /* Argument list execve() */
     char *argv[MAXARGS]; /* cmdline을 공백을 기준으로 쪼개어 저장하는 문자열 배열이다. */
     char buf[MAXLINE]; /* Holds modified command line */
     char buf[MAXLINE]; /* cmdline을 그대로 저장하는 버퍼 */
     int bg; /* Should the job run in bg or fg? */
     int bg; /* 실행할 명령이 백그라운드 실행인지 여부를 나타내는 플래그이다. */
     pid_t pid; /* Process id */
     pid_t pid; /* 새로 생성한 자식 프로세스의 PID를 저장 */
      
      
     strcpy(buf, cmdline);
     strcpy(buf, cmdline); /* cmdline을 buf에 복사한다. */
     bg = parseline(buf, argv);
    /* cmdline을 공백단위로 분리하여 이를 argv에 저장한다.
     if (argv[0] == NULL)
    명령어 뒤에 &가 붙어있다면 백그라운드 실행이라는 뜻이므로 bg의 플래그를 1로 설정한다. */
     bg = parseline(buf, argv);  
 
     if (argv[0] == NULL) /* 엔터만 입력된 경우이면 아무런 작업도 하지 않는다. */
         return; /* Ignore empty lines */
         return; /* Ignore empty lines */
 
   
     if (!builtin_command(argv)) {
    /* argv가 내장된 명령어인지 확인하고 내장된 명령어라면 내부에서 실행한다. */
         if ((pid = fork()) == 0) { /* Child runs user job */
     if (!builtin_command(argv)) { /* 내장된 명령어가 아닌 경우 */
             if (execve(argv[0], argv, environ) < 0) {
         if ((pid = fork()) == 0) { /* 자식 프로세스를 생성한다. */
             if (execve(argv[0], argv, environ) < 0) { /* 자식 프로세스 내에서 실제 명령어를 실행시킨다. */
                 printf("%s: Command not found.\n", argv[0]);
                 printf("%s: Command not found.\n", argv[0]);
                 exit(0);
                 exit(0);
             }
             }
         }
         }
        /* Parent waits for foreground job to terminate */
     
         if (!bg) {
         if (!bg) { /* foreground 실행 */
             int status;
             int status;
             if (waitpid(pid, &status, 0) < 0)
             if (waitpid(pid, &status, 0) < 0) /* foreground 작업인 경우 부모 프로세스는 해당 작업의 종료를 기다린다. */
                 unix_error("waitfg: waitpid error");
                 unix_error("waitfg: waitpid error");
         } else {
         } else { /* background 실행 */
             printf("%d %s\n", pid, cmdline);  // 개행 추가
             printf("%d %s\n", pid, cmdline);  /* waitpid()를 호출하지 않고 PID만 출력 후 즉시 다음 명령을 받을 준비를 한다.*/
         }
         }
     }
     }
55번째 줄: 59번째 줄:
}
}
</syntaxhighlight>
</syntaxhighlight>


==각주==
==각주==
[[분류:컴퓨터 시스템]]
[[분류:컴퓨터 시스템]]

2025년 3월 15일 (토) 15:31 판

상위 문서: Signals and Nonlocal jumps

개요

Shell이란 사용자 명령을 실행하는 애플리케이션 프로그램이다. 다음은 shell의 대표적인 예시이다.

  • sh : 오리지널 Unix 쉘 (Stephen Bourne, AT&T Bell Labs, 1977)
  • csh/tcsh : BSD Unix C 쉘
  • bash : Bourne-Again Shell (리눅스 기본 쉘)

Shell은 아용자의 명령어를 입력받고, 이를 실행시키는 식으로 작동한다.

예시

int main() {
    char cmdline[MAXLINE]; /* 명령어를 입력받을 버퍼이다. */
    while (1) {
        /* read */
        printf("> ");
        Fgets(cmdline, MAXLINE, stdin); /* 명령어를 입력받는다. */
        if (feof(stdin))
            exit(0);
        
        /* evaluate */
        eval(cmdline); /* 명령어를 실행시킨다 */
    }
}
void eval(char *cmdline) { /* cmdline은 사용자가 입력한 명령어 문자열이다. */
    char *argv[MAXARGS]; /* cmdline을 공백을 기준으로 쪼개어 저장하는 문자열 배열이다. */
    char buf[MAXLINE]; /* cmdline을 그대로 저장하는 버퍼 */
    int bg; /* 실행할 명령이 백그라운드 실행인지 여부를 나타내는 플래그이다. */
    pid_t pid; /* 새로 생성한 자식 프로세스의 PID를 저장 */
    
    strcpy(buf, cmdline); /* cmdline을 buf에 복사한다. */
    /* cmdline을 공백단위로 분리하여 이를 argv에 저장한다. 
    명령어 뒤에 &가 붙어있다면 백그라운드 실행이라는 뜻이므로 bg의 플래그를 1로 설정한다. */
    bg = parseline(buf, argv); 

    if (argv[0] == NULL) /* 엔터만 입력된 경우이면 아무런 작업도 하지 않는다. */
        return; /* Ignore empty lines */
    
    /* argv가 내장된 명령어인지 확인하고 내장된 명령어라면 내부에서 실행한다. */
    if (!builtin_command(argv)) { /* 내장된 명령어가 아닌 경우 */
        if ((pid = fork()) == 0) { /* 자식 프로세스를 생성한다. */
            if (execve(argv[0], argv, environ) < 0) { /* 자식 프로세스 내에서 실제 명령어를 실행시킨다. */
                printf("%s: Command not found.\n", argv[0]);
                exit(0);
            }
        }
       
        if (!bg) { /* foreground 실행 */
            int status;
            if (waitpid(pid, &status, 0) < 0) /* foreground 작업인 경우 부모 프로세스는 해당 작업의 종료를 기다린다. */
                unix_error("waitfg: waitpid error");
        } else { /* background 실행 */
            printf("%d %s\n", pid, cmdline);  /* waitpid()를 호출하지 않고 PID만 출력 후 즉시 다음 명령을 받을 준비를 한다.*/
        }
    }
    return;
}


각주