Love Every Moment

〔LINUX/UNIX〕리디렉션(Redirection)과 파이프(Pipe) 본문

PROGRAMMING::CORE/Operating System

〔LINUX/UNIX〕리디렉션(Redirection)과 파이프(Pipe)

해 송 2021. 6. 25. 18:58
반응형

 

0. 개요

유닉스 이전의 운영 체제에서는 프로그래머가 직접 입·출력장치를 설정하고 연결했어야 했다. 하지만 유닉스에서는 데이터 스트림(Data Stream) 이라는 개념을 이용하여 장치를 추상화함으로써 open, read, write 하면 자동으로 입·출력 장치가 연결되도록 하였다.

스트림(Stream)은 컴퓨터에 연결되는 여러 장치들을 통일된 방식으로 다루기 위한 가상적인 개념이다. 이를 통해 프로그래머는 데이터가 어디서 나와 어디로 가는지 신경쓰지 않고 자유롭게 이용할 수 있다. 표준 스트림(Standard Stream) 은 프로세스가 생성되면 기본적으로 생기는 입·출력을 위한 채널이다.

여기에는 표준 입력(Stdin), 표준 출력(Stdout), 표준 에러(Stderr) 가 있으며 터미널을 열면 쉘 프로세스의 표준 입력, 표준 출력, 표준 에러가 모두 터미널에 연결되어 사용자로부터 입력을 받고 출력한다.

 


 

 

1. 파일 서술자(File Desciptor) 

 

 

유닉스에서는 모든 장치들을 파일로 관리한다. 표준 스트림 역시 각각 표준 입력은 /dev/stdin 에, 표준 출력은 /dev/stdout/ 에, 표준 에러는 /dev/stderr 에 파일로 존재한다. 그리고 이 파일들은 우리가 사용하기에 편한 이름으로 보이지만 실제 프로그램 실행시에는 파일 디스크립터라는 양의 정수 번호에 의해 처리된다. 

 

(1) 표준 입력(Stdin)

  • FD: 0번
  • 사용자가 터미널에 직접 정보를 입력하는 채널
  • <unistd.h>  에  STDIN_FILENO  매크로로 정의되어 있다.

(2) 표준 출력(Stdout)

  • FD: 1번
  • 실행 결과가 출력되는 채널
  • <unistd.h> 에  STDOUT_FILENO  매크로로 정의되어 있다.

(3) 표준 에러(Stderr)

  • FD: 2번
  • 실행시 발생한 에러가 출력되는 채널

 

 

〔Linux/Unix〕파일 디스크립터(File Descriptor)란?

1. 파일 디스크립터 리눅스 운영 체계에서 파일에 대한 정보를 기술하고 유지하는 기억 장치의 영역 리눅스는 물리적 장치들을 일종의 파일로 관리 특히 리눅스 쉘은 작업에 필요한 파일들을 일

love-every-moment.tistory.com

 

 


 

 

2. 리디렉션(Redirection)

 

리디렉션 기호를 사용할 때에는 좌측에 파일 디스크립터 번호를 적어주어야 하지만 그렇지 않을 경우에는 표준 스트림(Standard Stream) 이 사용된다. < 와 << 기호는 입력이므로 좌측값 0 을 기본으로, > 와 >> 기호는 출력이므로 좌측값 1 을 기본으로 한다.

(1) 입력 리디렉션: <

  • 지정된 파일의 내용을 표준 입력으로 넘겨준다.
  • 좌측값 0 을 기본값으로 한다.
cat < file.txt
→ ABCDE 출력 (원래 file.txt 에 들어있던 내용)

 

(2) 덮어쓰기 출력 리디렉션: >

  • 표준 출력에 전달된 내용을 지정된 파일로 넘겨준다.
  • 좌측값 1을 기본으로 한다.
echo hello > file.txt
cat file.txt
→ hello 출력 (기존 file.txt 의 내용에 hello 가 덮어쓰여짐)

 

(3) 추가하기 출력 리디렉션: >>

  • > 와 마찬가지로 표준 출력에 전달된 내용을 지정된 파일로 넘겨준다.
  • 다만 차이점은 > 은 기존의 내용을 삭제하고 덮어쓰지만 >> 은 기존의 내용에 추가한다는 점이다.
  • 좌측값 1을 기본으로 한다.
cat file.txt
→ hello 출력
echo "world" >> file.txt
cat file.txt
→ hello
     world
     출력 (기존 file.txt 의 내용에 world 가 추가됨)

 

(4) 에러 출력 리디렉션: 2>

  • 에러 출력문을 해당 파일로 보낸다.
  • /dev/null 은 휴지통처럼 주기적으로 비워지는 공간이므로 보통 이곳으로 저장한다.
 cmd123
→ bash: cmd123: command not found 출력 (존재하지 않는 명령어이므로 에러 메시지 출력됨)
cmd123 2> file.txt
cat file.txt
bash: cmd123: command not found 출력

 

(5) Here Documents: <<

  • 구분자를 통해 "여기까지가 문서"라는 것을 나타낸다.
  • 구분자 이전까지 입력받은 내용을 임시 파일로 저장해서 명령어에 전달한다.
  • 보통은 EOF 를 구분자로 자주 사용한다.
  • 좌측값 0을 기본으로 한다.
cat << EOF > file.txt
1
2
3
EOF
  • 좌측에 FD 를 사용하여 3번 FD 에 내용을 입력해보자.
exec 3<< EOF
1
2
3
EOF

cat /dev/fd/3 (또는 cat <&3)
→ 1
→ 2
→ 3

만약 다시 한 번 cat /dev/fd/3 을 입력한다면 아무것도 출력되지 않는다.

exec <&3-  을 통해 FD 를 닫는다.

 

 

리눅스 - Here Document(<<)

참고자료 1. 히어 도큐먼트(Here-Document) 히어 도큐먼트는 입력 받은 내용을 임시 파일로 생성해서 명...

blog.naver.com

 

 

시스템 프로그래밍 - shell 구현

받으신 자료 유료 레포트 사이트에 올리지 말아주세요. shell 설계 및 소스코드 포함 문서 아래는 파일 내용 중 일부 나. 프로그램 구조 1) fork() 수행

freewise.tistory.com

 


 

 

3. 리눅스 명령어 작동 원리

 

사용자는 리눅스 커널과 통신하기 위해서 리눅스 쉘(Shell)을 사용한다. 리눅스 쉘은 커널과 운영체제를 이어주는 역할을 한다. 자신이 어떤 쉘을 사용하는지 확인하려면  echo $SHELL  을 터미널에 입력하면 된다. 기본적으로 리눅스 환경에서는 /bin/bash   일명 배쉬쉘 이라고 부르는 쉘을 사용한다. 쉘의 종류로는 bash, sh, csh 등이 있다.

이러한 쉘을 사용하기 위해서 필요한 것이 터미널이다. 터미널은 커맨드를 입력하여 쉘을 실행하기 위한 포장(Wrapper) 프로그램이다. 터미널과 쉘은 언제나 함께 실행될 수밖에 없다. 터미널에서 명령어 입력칸에 뜨는 프롬프트의 종류는 다음과 같다.

  • $: 보통 유저(Normal User)
  • #: 시스템 관리자(Root / Administrator)
  • %: C 쉘에서의 프롬프트 표시

 

터미널은 하나의 프로세스 이다. 사용자가 터미널에 'ls', 'cd', 'cat' 등의 명령어를 입력하면 해당 터미널의 정보를 기준으로 백그라운드에 자식 프로세스가 fork 되어 명령어를 실행하게 된다.

$  ls
→ fork() 로 자식프로세스 한 개가 생성된다.
→ 백그라운드에서 부모 프로세스의 정보를 기준으로 stdin 을 통해 정보를 입력 받는다.
→ stdout 을 통해 ls 명령어를 호출한 터미널로 정보를 반환한다.

 

 


 

 

4. 파이프(Pipe)

 

이와 같이 터미널은 하나의 프로세스이며 명령어 실행은 해당 터미널의 정보를 기준으로 백그라운드에 자식 프로세스가 fork 되어 진행된다. 여기서 파이프를 사용하여 여러 개의 명령어를 입력할 수도 있다. 파이프는 부모 프로세스에서 fork() 를 통해 자식 프로세스를 생성함으로써 부모-자식 프로세스 간에 통신할 수 있도록 해준다. 

$ ls | sort | less
→ ls 가 동작하는 자식 프로세스 따로 시작
→ sort 가 동작하는 자식 프로세스 따로 시작
→ less 가 동작하는 자식 프로세스 따로 시작

 

각각의 프로세스는 명령어를 실행했던 터미널 프로세스의 자식 프로세스로서 백그라운드에서 시작한다. 이를 가능하게 해주는 것이 fork() 함수이다. 부모 프로세스인 터미널에서 fork()로 인해 생긴 자식 프로세스들은 모두 병렬로 처리된다. 

 

 

간단히 A | B | C | D | E 로 표현하여 설명하자면 A 의 stdout(1) 을 B 는 stdin(0) 으로 읽어들인다. A의 stdout1) 을 받기 전까지 B 프로세스는 대기(Wait) 상태에 있다. 마찬가지로 B의 stdout(1)은 C의 stdin(0)으로 읽어들여진다. 

파이프는 <unistd.h>의 pipe(int pipefd[2])  함수를 통해 생성할 수 있다. 인자로 전달되는 배열에는 파이프의 양 끝단을 가리키는 파일 디스크립터(FD)가 입력된다. pipefd[0]은 파이프의 읽기를 위한 채널, pipefd[1]은 파이프의 쓰기를 위한 채널이다. 이렇게 생성된 파이프는 단방향 데이터 전송 기능을 수행한다. 

 

 

 

 

Unix Pipes

Unix Pipes A Unix pipe provides a one-way flow of data. For example, if a Unix users issues the command who | sort | lpr then the Unix shell would create three processes with two pipes between them: A pipe can be explicitly created in Unix using the pipe s

web.cse.ohio-state.edu

 

 


 

 

 

REFERENCE:

 

 

Redirections | Introduction

Redirection 지금은 터미널 프로그램을 열면 별다른 설정 없이 바로 명령을 입력할 수 있고 출력을 볼 수 있지만 unix 이전의 OS 에서는 프로그래머가 직접 입,출력장치를 (punch card reader, magnetic tape dri

mug896.github.io

 

리눅스 파이프(pipe) 에 대한 설명 ( '|' )

리눅스에서 저희는 파이프( | )를 자주 사용합니다. 이 파이프에 대해 알아보려고 합니다. 그럼 우선 리눅스 명령이 어떤식으로 실행되는지 알아야 합니다. 1. 리눅스 쉘 사용자는 리눅스 커널과

hwan-shell.tistory.com

 

반응형
Comments