Bash 내장 제어 구조/명령 리디렉션 작동 방식

Bash 내장 제어 구조/명령 리디렉션 작동 방식

제가 관심 있는 것은 bash 내장 제어 구조와 기능을 사용하여 기술적으로 리디렉션을 구현하는 방법입니다.

예를 들어 다음 명령이 있습니다.

while read line; do echo $line; done < lines.txt | tac > ~/reversed.txt

표준 입력(lines.txt)을 read명령( 인수 while)에 연결하는 메커니즘은 무엇이며 do본문을 표준 출력(파이프)에 연결하는 메커니즘은 무엇입니까? 분명히 일부 상황별 규칙이 적용되지만(외부 명령 리디렉션과 반대) 이러한 규칙은 정확히 무엇이며 bash는 이를 기술적으로 어떻게 구현합니까?

답변1

일반적으로 UNIX 쉘은 다open엽니간단히필요한 파일을 성능상의 이유로(매우 비싸기 때문에 ) 내장 명령과 다를 수 있지만 의미는 동일합니다.forkdup2execveforkexecve

그러나 명령줄 구문 분석 규칙을 참조하는 경우 이는 POSIX에 설명되어 있습니다. 내장 프로그램과 외부 프로그램을 구별하지 않습니다.

답변2

파일 설명자 리디렉션d0파일을 안팎으로 전송하는 작업에는 다음 단계가 포함됩니다.

  1. 파일을 엽니다. 파일이 파일 설명자에서 열립니다.d1.
  2. 사본 설명자d0현재 사용되지 않는 파일 설명자에d2그것은보다 크다d0. 이 작업은 F_DUPFD다음 명령으로 수행할 수 있습니다.fcntl시스템 호출. 만약에d0열리지 않으면 이 단계에서는 아무 작업도 수행되지 않습니다.
  3. 복사d1도착하다d0. 이는 F_DUPFD또는 로 수행 할 수 있습니다.dup2.
  4. 폐쇄d1.

반복적인 셔플링이 필요한 이유는 파일을 열 때 애플리케이션이 파일 설명자를 선택할 수 없기 때문입니다. 다음 조건이 충족되면 2~4단계를 생략할 수 있습니다.d1=d0그러나 쉘은 이를 보장할 수 없습니다.

외부 명령에 리다이렉션을 적용하면 자식 프로세스가 생성된 후 자식 프로세스에서 실행된다.fork그러나 외부 명령을 실행하기 전에execve. 리디렉션이 내부 셸 명령(예: 함수 호출, 루프 등)에 적용될 때 이러한 단계는 원래 프로세스에서 수행되어야 하며, 셸은 리디렉션된 명령이 완료된 후 원본 파일 설명자 상태를 복사하여 복원해야 합니다.d2로 돌아가d0그리고 닫아라d2(또는 그냥 닫으세요.d0처음에 열려 있지 않은 경우).

파이프에는 유사한 단계가 포함되지만 파이프를 생성하면 두 개의 파일 설명자(읽기 측 및 쓰기 측)가 생성되고 두 개의 하위 프로세스가 있으므로 조금 더 복잡합니다.

  1. 파이프라인 만들기pipe. 시스템 pipe호출은 파일 설명자 쌍을 반환합니다.아르 자형,}.

  2. 파이프의 왼쪽:

    1. 폐쇄아르 자형.
    2. 복사본을 만들고 무작위로 이동1로.
  3. 파이프의 오른쪽:

    1. 폐쇄.
    2. 복사본을 만들고 무작위로 이동아르 자형0으로.
  4. 하위 프로세스에서 실행되는 파이프라인 양쪽의 셸에서 상위 프로세스가 닫힙니다.아르 자형그리고, 파이프의 양쪽이 종료될 때까지 기다립니다.

    상위 프로세스의 파이프 오른쪽에서 실행되는 셸에서 셸은 왼쪽이 종료될 때까지 기다린 다음 0을 닫고 원래 파일 설명자를 0에서 복원합니다.

소스 코드를 읽거나 디버거를 사용하여 실행을 추적함으로써 쉘의 기능에 대해 배울 수 있습니다. 예를 들어 Linux에서는 실행 중인 시스템 호출을 봅니다.

strace sh -c '…'

1 고대 쉘(POSIX 이전)은 하위 프로세스에서 리디렉션된 복잡한 명령을 실행했으므로 리디렉션 복구가 필요하지 않았습니다.

관련 정보