리눅스에서 저희는 파이프( | )를 자주 사용합니다.
이 파이프에 대해 알아보려고 합니다.
그럼 우선 리눅스 명령이 어떤식으로 실행되는지 알아야 합니다.
1. 리눅스 쉘
사용자는 리눅스 커널과 통신하기 위해서 리눅스 쉘이라는 녀석을 사용합니다.
정확히는 커널과 운영체제를 이어주는 녀석입니다.
기본적으로 리눅스를 사용하는 환경은 /bin/bash 라는 쉘을 사용합니다. 일명 배쉬쉘....
자신이 어떤 쉘을 사용하는지 확인하려면 다음과 같은 명령어를 입력해주시면 됩니다.
# echo $SHELL
저희가 이런 쉘을 사용하기 위해서 터미널 창을 열게 됩니다.
이런 터미널은 하나의 프로세스입니다.
그리고 'ls', 'cd', 'cat' 등의 명령어는 이 터미널이 갖고있는 정보를 기준으로 실행되게 됩니다.
2. 리눅스 파이프
앞에서 터미널은 하나의 프로세스이고, 명령어 실행은 해당 터미널의 정보를 기준으로 백그라운드에 자식프로세스가 fork되어 명령어를 실행하게 됩니다.
즉, 터미널에서 'ls' 라는 명령어를 입력하면, 자식프로세스 1개가 fork되어 백그라운드에서 부모프로세스의 정보를 기준으로 해당 명령어 즉, stdin을 통해 정보를 입력받고 stdout을 통해 ls 명령어를 호출한 터미널로 정보를 반환하는 식으로 동작 합니다.
그럼 파이프 끼리 연결되면 어떻게 되느냐??
예를들어 #ls | sort | less
명령어를 입력하면 다음과 같이 동작하게 됩니다.
ls 동작하는 프로세스 따로
sort 동작하는 프로세스 따로
less 동작하는 프로세스 따로
동작하게되며 위 3개의 프로세스는 명령어를 실행한 터미널 프로세스의 자식프로세스로 백그라운드에서 시작하게 됩니다. 또한 자식 프로세스들은 exec
라는 시스템 콜 함수를 통해 fork
가 발생하게 됩니다.
※중요
부모 프로세스(터미널)에서 fork로 인해 자식프로세스들이 생기면 자식 프로세스들은 모두 병렬로 처리되게 됩니다.
또한 모든 프로세스는 exec 방식으로 호출되어 프로세스 PID는 모두 동일하게 갖게 됩니다.
프로세스들은 stdin, stdout 방식으로 A | B | C 가 호출된다면,
A의 stdout을 B는 stdin으로 읽어들어오며 C 또한 마찬가지로 동작하게 됩니다.
그리고 A의 stdout을 받기 전까지 프로세스는 B프로세스는 wait 상태가 되며, C또한 마찬가지 상태가 됩니다.
이를 그림으로 보면
이런식으로 진행되게 됩니다. 즉 왼쪽에서 오른쪽으로 가게 되지요.
그럼 예제를 한번 봅시다.
#ls | sort | less
이런식으로 결과 화면이 나오게 됩니다.
root 계정의 home 디렉토리 내용이구요.
그럼 다음 명령어를 실행해보시기 바랍니다.
현재 경로가 /root 라는 가정하에....
#ls | sort | cd /dev/fd
실행 결과가 안나옵니다.
예상시나리오라면 다음과 같습니다.
1. /root 경로에 에서 ls | sort 명령어가 실행된 후
2. /root 경로에서 /dev/fd 경로로 변경된다.!!
라는 가정을 생각하셨을 것입니다.
하지만 아무것도 나온 결과가 없죠.
그 이유는 다음과 같습니다.
1. 부모 프로세스에서(터미널) fork로 자식 프로세스가 생겼을 때, 자식 프로세스는 별도의 환경을 갖게 됩니다.
왜냐? 프로세스니깐요. 프로세스와 쓰레드의 차이를 생각하시면 될 것 같습니다.!!
2. 그렇기 때문에 저기 마지막 부분 cd /dev/fd 부분은 자식 프로세스 내의 경로로 변경되며 실행이 종료 됩니다.
때문에 stdout이 cd /dev/fd 명령어 실행한 프로세스에서 내부적으로 일어난 후 종료되기 때문에,
부모 프로세스(터미널) 입장에선 return 되는 stdout이 없어져 버리는 것이죠.
3. 해당 명령어를 실행하기 위해선
# ls | sort && cd /dev/fd
명령어를 통해 해결해야 합니다.
아시겠나요??
참고 래퍼런스
en.wikipedia.org/wiki/Pipeline_(Unix)
brandonwamboldt.ca/how-linux-pipes-work-under-the-hood-1518/
'프로그래밍 > 리눅스' 카테고리의 다른 글
Shell script STDOUT vs STDERR (2>&1) (0) | 2021.09.26 |
---|---|
Linux awk 사용법 및 응용법. (0) | 2021.07.20 |
c++] make, makefile의 사용방법(기본적인 설명) (1) | 2020.05.18 |
gcc/g++ 분할 파일 컴파일 하기. (0) | 2020.05.17 |
gcc / g++ 사용법과 설명 (4) | 2020.05.17 |
댓글