Home Minishell ② 배경 지식
Post
Cancel

Minishell ② 배경 지식

Shell

동작 방식

Untitled

  1. 파일 또는 터미널로부터 입력을 받는다.
  2. 따옴표 규칙을 지키며 입력을 단어연산자로 쪼갠다. 이러한 토큰들은 메타문자로 구분된다.
  3. 토큰들을 간단하고 복합된 명령어로 파싱한다.
  4. 다양한 shell 확장을 진행한다.
  5. 필요한 리다이렉션들을 수행하고 해당 연산자와 피연산자들을 인자 리스트에서 제거한다.
  6. 명령을 실행한다.
  7. 선택적으로 명령이 끝나기를 기다렸다가 종료 상태를 수집한다.

Shell 확장 (Shell Expansions)

파일명 확장 (filename expansion)

  • 기능
    • 와일드카드 등의 문자가 경로나 파일로 확장된다.
  • 예시

    1
    2
    
      $ echo *
      Applications Code Desktop Documents Downloads Library Movies Music Pictures goinfre
    
  • 기타
    • 다음과 같은 옵션을 추가해 파일을 지칭할 수도 있다.

      문자 클래스매칭 문자
      [:alnum:]모든 알파벳과 숫자
      [:alpha:]모든 알파벳
      [:digit:]모든 숫자
      [:lower:]소문자 알파벳
      [:upper:]대문자 알파벳
    • 예시

      1
      2
      3
      4
      5
      
        $ echo *
        Test2 Test4 test1 test3
              
        $ echo [[:lower:]]*
        test1 test3
      

틸드 확장 (tilde expansion)

  • 기능
    • 틸드 ~ 문자를 유저 홈 디렉토리로 해석한다.
  • 예시

    1
    2
    
      $ echo ~
      /Users/taehooki
    

산술 확장 (arithmetic expansion)

  • 기능
    • 계산기와 유사하게 사용할 수 있다. 정수 간의 연산만 가능하다.(zsh는 가능)
    • $((expression)) 와 같이 사용한다.
    • 사용 가능한 연산자는 다음과 같다.

      연산자설명
      +덧셈
      -뺄셈
      *곱셈
      /나눗셈(소수가 아닌 몫만 구해진다)
      %나머지
      **거듭제곱
  • 예시

    1
    2
    
      $ echo $((6 * 7))
      42
    
    1
    2
    
      $ echo $((6 / 5))
      1
    

중괄호 확장 (brace expansion)

  • 기능
    • 임의의 문자열을 생성한다.
    • 패턴들은 콤마로 나뉘어진다.
    • .. 과 같이 사용하면 범위를 표현할 수 있다.
  • 예시

    1
    2
    
      $ echo a{d,c,b}e
      ade ace abe
    
    1
    2
    3
    4
    5
    6
    7
    
      $ touch a{d,c,b}e
        
      $ ls -l
      total 0
      -rw-r--r--  1 taehooki  2022_seoul  0 Nov 21 15:46 abe
      -rw-r--r--  1 taehooki  2022_seoul  0 Nov 21 15:46 ace
      -rw-r--r--  1 taehooki  2022_seoul  0 Nov 21 15:46 ade
    
    1
    2
    
      $ echo {a..z}
      a b c d e f g h i j k l m n o p q r s t u v w x y z
    

매개변수 확장 (shell parameter expansion)

  • 기능
    • 변수를 사용할 수 있다.
    • ${parameter} 와 같이 사용한다.
  • 예시

    1
    2
    
      $ echo $USER
      taehooki
    
  • 기타
    • 변수를 정의하는 방법은 다음과 같다.

      1
      
        $ my_variable=42
      
      1
      2
      
        $ echo $my_variable
        42
      

명령어 치환 (command substitution)

  • 기능
    • 명령어의 출력이 명령어 자신을 대체할 수 있다.
  • 예시
    • 파일의 경로를 찾는 명령어인 which를 통해 brew의 위치를 찾으면 다음과 같이 출력된다.

      1
      2
      
        $ which brew
        /Users/taehooki/.brew/bin/brew
      
    • 이 때 해당 명령어를 $(command) 또는 command 로 묶어 다음과 같이 사용하면 위 명령어의 결과가 해당 명령어를 대체하게 된다.

      1
      2
      
        $ ls -l $(which brew)
        -rwxr-xr-x  1 taehooki  2022_seoul  4565 Nov 18 16:03 /Users/taehooki/.brew/bin/brew
      

단어 분할 (word splitting)

  • 설명
    • 셸에서는 $IFS의 각 문자를 구분자로 취급하고 단어를 분할하는 데 사용한다.
      • IFS (Internal Field Separator)
        • 외부 프로그램을 실행할 때 입력되는 문자열을 나누는 기준이 되는 문자를 정의하는 환경 변수
        • 기본값 : 공백, 탭, 개행문자

    Untitled

용어 정리

  • POSIX
    • Unix 기반의 오픈 시스템 표준
  • builtin
    • 파일 시스템 내의 실행가능한 프로그램 형태로 있지 않고, 셸 자체에 내장되어 있는 명령어
  • control operator
    • 제어 기능을 하는 토큰
    • 개행문자 또는 다음 중 하나이다 : ||, &&, &, ;, ;;, ;&, ;;&, |, |&, (, ).
  • exit status
    • 명령어에 의해 호출자에게 돌아온 값.
    • 8비트로 제한되어 있으며 최대 값은 255.
  • field
    • 셸 확장들 중 하나의 결과로 나온 문자의 단위.
    • 확장 이후에 실행될 때 , 필드들은 명령어 이름과 인자로 사용된다.
  • job
    • 파이프라인을 구성하는 프로세스들의 집합, 해당 프로세스에서 나온 같은 프로세스 그룹에 속하는 다른 프로세스들.
  • job control
    • 사용자가 프로세스의 실행을 선택적으로 중지하고 재개할 수 있는 메커니즘
  • metacharacter
    • 따옴표로 감싸져있지 않을 경우 단어를 분리시키는 문자
    • 공백, 탭, 개행문자 또는 다음 중 한 문자이다 |, &, ;, (, ), <, >.
  • operator
    • control operator와 redirection operator가 있다.
    • 연산자는 최소 한 개의 따옴표가 없는 metacharacter를 포함한다.
  • process group
    • 동일한 프로세스 그룹 ID를 가진 연관된 프로세스들의 집합
  • process group ID
    • 프로세스 그룹을 대표하는 고유한 식별자. 프로세스의 lifetime동안 사용한다.
  • reserved word
    • 셸에서 특별한 의미를 갖는 word. for, while 등이 있다.
  • return status
    • = exit status
  • signal
    • 프로세스가 커널에 의해 시스템 내에서 이벤트의 발생을 전달받는 메커니즘
  • token
    • 셀에서 하나의 유닛으로 취급받는 일련의 문자들
    • word 또는 operator 중 하나이다.
  • word
    • 셀에서 하나의 유닛으로 취급받는 일련의 문자들
    • 따옴표 없는 metacharacters는 제외한다.

파싱

Untitled

리다이렉션

  • 입력
    • > : 표준 출력을 리다이렉션한다. 동일한 파일이 존재한다면 덮어 쓰여진다.
    • >> : 표준 출력을 리다이렉션한다. 동일한 파일이 존재한다면 뒷부분에 이어서 쓴다.
  • 출력
    • < : 표준 입력을 리다이렉션한다.
    • << : here document. 뒤에 오는 구분자가 올 때까지 입력을 받는다.

환경 변수

  • 의미
    • 프로세스가 컴퓨터에 동작하는 방식에 영향을 미치는 동적인 값들의 모임
  • 셸 변수(shell variable)와의 차이점
    • 환경 변수는 global 하게 사용가능한 변수이다.
    • 그에 반해 셸 변수는 현재의 셸에서만 사용가능한 변수이다.
  • 명명 규칙
    • 대문자, 소문자, 밑줄 문자(_)만이 올 수 있다.
  • 사용 예시

    1
    2
    3
    
      $ QUESTION=ANSWER
      $ echo $QUESTION
      ANSWER
    
  • env, declare, export의 차이점
    • env : 단일 명령에 대한 환경 변수를 설정할 수 있다.
    • declare : 셸 변수를 설정한다.
    • export : 셸 변수를 환경 변수로 만든다.

전역변수

  • data 영역에 위치한다.(정적 변수와 동일)
  • 별도의 초기화를 하지 않으면 0으로 초기화 된다.

터미널, 콘솔, 셸, 커널의 차이점

터미널 (terminal)

Untitled

  • 터미널을 실행했을 때 켜지는 사각형의 창
  • 사용자로부터 명령어 형식의 입력을 받아서, 출력을 화면에 표시하는 역할
  • 정보를 처리하는 것이 아님

콘솔 (console)

  • 윈도우OS 상에서 터미널의 또 다른 이름
  • 콘솔은 직접 실행시키는 것이 아니라 명령 프롬프트를 통해서 실행시킨다.

셸 (shell)

Untitled

  • 터미널 상에서 명령을 입력하고 엔터를 눌렀을 때 터미널이 명령어를 넘겨주는 곳
  • 종단 사용자(end-user)와 커널 사이의 인터페이스
  • 예시) TCSH, KSH, Seashell, Bash

커널 (kernel)

Untitled

  • OS의 제일 안쪽에 위치한 프로그램
  • shell이 사용자의 명령을 커널의 언어로 변환하면, 커널은 OS 라이브러리와 디바이스 드라이버를 사용해 명령어를 실행시킨다.

과제 허용 함수

  • readline
    • 헤더
      • #include <readline/readline.h>
    • 사용 예시

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
        int	main(void)
        {
        	char	*str;
              
        	while (1)
        	{
        		str = readline("minishell$ ");
        		if (strlen(str) == 0)
        			continue ;
        		printf("you typed : %s\n", str);
        		free(str);
        	}
        }
      
    • 기타
      • 컴파일 시 -lreadline 과 같이 include 옵션 지정
  • rl_on_new_line
    • 함수 원형
      • int rl_on_new_line(void)
    • 설명
      • 업데이트 함수에게 새 줄로 이동했다는 것을 알려준다. 주로 개행을 출력한 이후에 사용한다.
  • rl_replace_line
    • 함수 원형
      • void rl_replace_line (const char *text, int clear_undo)
    • 설명
      • rl_line_buffer의 내용을 변경한다.
    • 기타
      • 컴파일 시 include path 지정

        1
        
          -lreadline -L${HOME}/.brew/opt/readline/lib -I${HOME}/.brew/opt/readline/include
        
    • 유의사항
      • stdio.h를 readline헤더보다 먼저 include 해야함
  • rl_redisplay
    • 함수 원형
      • void rl_redisplay(void)
    • 설명
      • rl_line_buffer를 프롬프트에 재출력해준다.
  • add_history
    • 함수 원형
      • add_history(const char *string)
    • 설명
      • string을 history list 맨 뒤에 위치시킨다.
  • wait
    • 헤더
      • #include <sys/wait.h>
    • 함수 원형
      • pid_t wait(int *status)
    • 인자
      • status : 종료된 자식 프로세스의 상태가 저장됨
        • 정상 종료된 경우 : 하위 8비트에는 0, 상위 8비트에는 종료시 exit()에 들어있던 인수
        • 비정상 종료된 경우 : 하위 8비트에는 종료시킨 시그널 번호, 상위 8비트에는 0
  • getcwd
    • 헤더
      • #include <unistd.h>
    • 함수 원형
      • char *getcwd(char *buf, size_t size);
    • 설명
      • 현재 디렉토리의 full path를 \0로 끝나는 문자열로 buf에 저장
    • 인자
      • buf : full path를 저장할 저장공간
      • size : buf 에 할당된 저장공간 크기
    • 반환값
      • 성공한 경우 : 경로명에 대한 포인터
      • 실패한 경우 : NULL 포인터 반환. errno 설정.
    • 기타
      • buf가 NULL인 경우 자동으로 공간을 할당해준다.
  • chdir
    • 함수 원형
      • int chdir(const char *path)
    • 설명
      • 현재 작업 디렉토리를 변경한다.
    • 인자
      • path : 디렉토리의 경로명
    • 반환값
      • 성공 : 0 반환
      • 실패 : -1 반환. errno 설정.
  • stat
    • 헤더
      • #include <sys/stat.h>
    • 함수 원형
      • int stat(const char *path, struct stat *buf)
    • 설명
      • path가 가리키는 파일의 정보를 가져온다.
    • 인자
      • path : 상태를 알아볼 파일의 경로
      • buf : 상태를 저장할 stat 구조체
    • stat 구조체

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      
        struct stat {
                 dev_t           st_dev;           /* ID of device containing file */
                 mode_t          st_mode;          /* Mode of file (see below) */
                 nlink_t         st_nlink;         /* Number of hard links */
                 ino_t           st_ino;           /* File serial number */
                 uid_t           st_uid;           /* User ID of the file */
                 gid_t           st_gid;           /* Group ID of the file */
                 dev_t           st_rdev;          /* Device ID */
                 struct timespec st_atimespec;     /* time of last access */
                 struct timespec st_mtimespec;     /* time of last data modification */
                 struct timespec st_ctimespec;     /* time of last status change */
                 struct timespec st_birthtimespec; /* time of file creation(birth) */
                 off_t           st_size;          /* file size, in bytes */
                 blkcnt_t        st_blocks;        /* blocks allocated for file */
                 blksize_t       st_blksize;       /* optimal blocksize for I/O */
                 uint32_t        st_flags;         /* user defined flags for file */
                 uint32_t        st_gen;           /* file generation number */
                 int32_t         st_lspare;        /* RESERVED: DO NOT USE! */
                 int64_t         st_qspare[2];     /* RESERVED: DO NOT USE! */
             };
      
    • 반환값
      • 성공 : 0 반환
      • 실패 : -1 반환. errno 설정.
  • unlink
    • 함수 원형
      • int unlink(const char *path);
    • 설명
      • 디렉토리 엔트리를 제거한다.
        • 디렉토리 엔트리란?
          • 디렉토리를 표현하는 데에 사용되는 자료구조
          • 보통 파일 이름, 파일 속성 등 파일에 대한 다양한 정보가 저장됨.
          • 유닉스 계열에서는 파일명과 아이노드 번호만 저장됨.
      • 이름이 path인 링크를 제거하고 해당 링크가 참조한 링크 카운트를 감소시킨다.
      • 링크 카운트가 0이 되고 아무 프로세스도 파일을 열고 있지 않다면 해당 파일에 대한 리소스가 회수된다.
      • 링크 카운트가 0이지만 누군가 파일을 열고 있다면 해당 파일이 닫힐 때까지 파일의 삭제가 미뤄진다.
  • execve
    • 함수 원형
      • int execve(const char *path, char *const argv[], char *const envp[]);
    • 설명
      • 파일을 실행한다.
      • 호출한 프로세스를 새 프로세스로 변환한다.
    • 인자
      • path : 실행할 파일의 경로
      • argv : 인자 목록
      • envp : 환경 변수 목록
  • dup
    • 함수 원형
      • int dup(int fildes);
    • 설명
      • 존재하는 파일 디스크립터를 복제한다.
    • 반환값
      • 성공 : 새로운 파일 디스크립터
      • 실패 : -1 반환. errno 설정.

Ref.

GNU shell expansions
Shell expansions
환경 변수 - 위키백과, 우리 모두의 백과사전
bash - Environment variable vs Shell variable, what’s the difference? - Ask Ubuntu
[LINUX] IFS
Here document - Wikipedia
[minishell] 사용 가능 함수 정리
디렉토리 엔트리 - 위키백과, 우리 모두의 백과사전
bash - What is the difference between set, env, declare and export when setting a variable in a Linux shell?
What is Terminal, Console, Shell and Kernel? - GeeksforGeeks
01.리눅스 기초 - 쉘(Shell)과 디렉토리 구조

This post is licensed under CC BY 4.0 by the author.

Minishell ① Subject

Minishell ③ 구현 과정