ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Develop] Unix Shell 기능 구현
    Mhwan's Develope/C Languge 2020. 1. 2. 23:57

    ls -al명령어 실행 예시

     

    ##기능

     - Unix Shell의 각종 기능을 구현

     - 순차실행, 후면(background)실행, 입력 재지정, 출력재지정, 입출력 동시 재지정(redirection), 파이프 (pipe)

     

    ##간단 설명 및 알고리즘

     - 먼저 입력한 명령어를 적절히 파싱

     - 일반 실행 : argv에 파싱된 명령어를 넣고 일반적인 실행일 경우 자식프로세스가 execvp를 실행시키는 동안 부모 프로세스는 자식이 끝날때까지 기다림(wait)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    void executesLine(int isbg, char *argv[]){
        int status, pid;
     
        if ((pid=fork()) == -1)
            perror("fork failed");
        else if (pid != 0) {
            if(isbg==0)
                 pid = wait(&status);
            else {
                 printf("[1] %d\n", getpid());
                 waitpid(pid, &status, WNOHANG);    
            }
        } else {
            execvp(argv[0], argv);
        }
    }
    cs

     - 후면실행 : 자식이 끝날때까지 부모가 기다리지 않고 종료함, (waitpid 함수의 WNOHANG명령어를 사용)

     - 순차실행은 이들을 반복문으로 연속적으로 실행될 수 있게 구현

     - 리다이렉션 : dup2함수를 이용, 입력재지정일 경우 dup2(fd, 0)으로, 출력재지정일 경우 dup2(fd, 1)로, 입출력 동시 재지정일 경우 입력 재지정과 출력재지정 dup2를 모두 이어서 실행시켜주고 execvp함수를 통해 명령어를 실행시키면 됨

    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    void doRedirection(int flag, int is_bg, char *argv[], char* input, char * output){
        int input_fd, output_fd;
        int status, pid;
        
        if ((pid=fork()) == -1)
            perror("fork failed");
        else if (pid != 0) {
            if(is_bg==0)
                pid = wait(&status);
            else {
                printf("[1] %d\n", getpid());
                waitpid(pid, &status, WNOHANG);
            }
        } else {
            if (flag == 2) {
                if((input_fd = open(input, O_RDONLY))==-1){
                    perror(argv[0]);
                    exit(2);
                }
                dup2(input_fd, 0);
                close(input_fd);
                execvp(argv[0], argv);
            } else if (flag == 3) {
                output_fd = open(output, O_CREAT|O_TRUNC|O_WRONLY, 0600);
                dup2(output_fd, 1);
                close(output_fd);
                execvp(argv[0], argv);
            } else {
                if (input != NULL && output != NULL) {
                    input_fd = open(input, O_RDONLY);
                    dup2(input_fd, 0);
                    close(input_fd);
                    
                    output_fd = open(output, O_CREAT|O_TRUNC|O_WRONLY, 0600);
                    dup2(output_fd, 1);
                    close(output_fd);
                    execvp(argv[0], argv);
                }
            }
        }
    }
    cs

     - 파이프 : 파이프 수행을 위해 pipe함수에 입출력 모두의 파일 디스크립터인 fd[2]를 넣어서 각 모드를 실행하고, fork를 두번 실행하여 프로세서로 데이터를 전달하도록 구현

    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
    32
    33
    34
    void doPipe(char* arg1[], char* arg2[]){
        int fd[2];
        if(pipe(fd) == -1) {
            perror("Pipe failed");
            exit(1);
        }
     
        if(fork() == 0){            
            close(STDOUT_FILENO);  
            dup2(fd[1], 1);        
            close(fd[0]);    
            close(fd[1]);
     
            execvp(arg1[0], arg1);
            perror("parent execvp failed");
            exit(1);
        }
     
        if(fork() == 0) {           
            close(STDIN_FILENO); 
            dup2(fd[0], 0);      
            close(fd[1]);  
            close(fd[0]);
     
            execvp(arg2[0], arg2);
            perror("child execvp failed");
            exit(1);
        }
     
        close(fd[0]);
        close(fd[1]);
        wait(0);
        wait(0);
    }
    cs

     

    ## 링크

    Github : https://github.com/mhwan/Myshell

     

    mhwan/Myshell

    Unix shell prompt (redirection, pipe, background executes etc..) - mhwan/Myshell

    github.com

     

    댓글

Designed by Mhwan.