**Input/Output (I/O)**은 단어 그대로 입력과 출력을 의미하며, 컴퓨터와 현실을 연결하는 통로이다.
모니터부터 시작해 키보드, 마우스, 심지어 네트워크 통신을 위한 것들 조차도 I/O이다.
I/O를 잘 제어하지 못하면 CPU와 I/O 사이의 병목 현상에 의해 컴퓨터의 속도가 느려지게 되고, I/O 처리가 원활하지 않은 경우 사용자의 입출력을 올바르게 받지 못해 원하는 동작을 수행할 수 없다.
사용자는 I/O에 직접 접근할 수 없으며 커널이 추상화한 값만을 이용해 접근할 수 있다. 이 때 사용하는 값이 **파일 디스크립터(File Descriptor, fd)**이다.
프로세스가 파일을 열어서 작업하는 상황이 있다고 했을 때, 텍스트 에디터 프로세스가 파일을 생성하거나 수정하기 위해 운영체제에 그 파일을 관리하기 위한 권한을 요청하면 운영체제는 **파일 디스크립터(File Descriptor, fd)**라는 번호를 할당해 반환한다. 프로세스는 운영체제가 할당한 fd를 이용해서 저장장치에 위치한 파일에 접근할 수 있다.
프로그램이 실행되면 파일 디스크립터를 관리하는 Descriptor Table이 생성되는데, 이 테이블은 Open File Description을 가리킨다. 최종적으로는 inode table을 가리키며 이때 inode는 리눅스의 파일과 디렉토리 시스템을 학습해보았다면 접해봤을 inode를 말한다.
프로세스가 열린 파일에 접근할 때 File Descriptor Table의 인덱스 번호를 사용하며 이를 fd라 부른다.
프로세스는 기본적으로 0, 1, 2번 파일 디스크립터가 할당되어 있으며 각각 standard input (stdin), standard output(stdout), **standard error (stderr)**을 의미한다. stdin은 표준 입력, stdout은 표준 출력, stderr은 오류 출력의 목적은 가진다. 이 fd들은 open()으로 직접 파일을 열지 않더라도 실행 초기에 운영체제가 할당한다. 따라서 새로운 파일을 열 경우 기본적으로 fd가 3부터 할당된다.
fd들도 파일의 형식으로 관리하며 /proc/[pid]/fd 에 있다.
**파이프(Pipe)**는 이전 명령의 출력을 다음 명령어의 입력으로 제공하는 기능이다.
해당 기능은 명령어가 아니며, 셸 상에서 | 기호를 이용한다.
#include <stdio.h>
int main()
{
char buffer[0x100];
scanf("%[^\n]s", buffer);
printf("output is \"%s\"\n", buffer);
}
해당 코드를 pipe.c 로 저장하고 컴파일 후 실행하고 hello pipe! 를 입력하면 output is "hello pipe!" 가 출력된다. pipe 로 한번 입력과 출력을 연결해준다면 output is "hello pipe!" 가 다시 프로그램의 입력으로 들어가기 때문에 output is "output is "hello pipe!"" 가 출력된다.