-
Standard Input (표준입력) 이해하기System 2023. 10. 16. 08:24728x90반응형
- 목차
소개.
프로그래밍 입문 수업을 들을 때, 표준 입출력에 대한 강좌가 꼭 하나씩 있곤 합니다.
Stdin.read() 와 같은 형식으로 코드 한 줄을 입력하고 나면,
키보드로 타이핑한 텍스트가 터미널로 출력되곤 했습니다.
사실 실무에선 이러한 코드를 다룰 일이 드물고,
UI 를 다루는 대부분의 프론트엔드 영역에서도 사용자의 input 을 다루는 코드들이 굉장히 추상화 되어있죠.
HTML 의 <input/> 태그, Android 나 IOS 에서도 사용자의 입력을 다루는 컴포넌트들이 추상화되어 있습니다.
그래서 표준 입력을 다루는 코드를 다룰 일은 거의 없습니다.
세월이 흘려서 궁금증이 생겨서 Standard Input 에 대한 글을 작성해보려고 합니다.
Standard Input 이란?
Standard Input (표준 입력) 은 Process 가 외부로부터 데이터를 전달받을 수 있는 대표적인 스트림입니다.
데이터 -> Standard Input Stream -> Process
와 같은 순서로 Process 는 Standard Input (표준 입력) 으로부터 데이터를 입력받습니다.
그 외에서 여러 방식의 데이터 전달 방식이 있습니다.
Socket 을 이용한 IPC 를 통해 Process 간의 통신이 가능하구요.
TCP Socket 를 활용하여 Network 통신이 가능합니다.
Socket 는 자체적인 Stream 또는 Buffer 를 다루기 때문에 Standard Input (표준 입력) 를 사용하지 않습니다.
즉, 제가 하고자하는 말은 "표준입력 이외에도 여러가지 방식으로 Process 가 데이터를 입력받을 수 있다" 는 뜻입니다.
Standard Input (표준 입력) 는 memory-based data structure 입니다.
Socket 처럼 파일 시스템 상에서 전용 파일이 존재하지 않습니다.
커널이 관리하는 메모리 상의 버퍼이구요.
데이터의 전달을 위해서 파일 또는 디스크의 리소스를 사용하지 않고, 메모리를 활용하게 됩니다.
키보드나 파일의 정보들이 표준입력을 위한 메모리 버퍼에 추가됨으로써 프로세스에게 데이터가 전달됩니다.
이러지는 글에서 표준입력과 관련된 여러 케이스와 테스트를 진행해보려고 합니다.
The Cases of Standard Input.
keyboard input.
표준입력과 키보드 인풋은 대표적인 표준입력의 방식입니다.
하드웨어 입력 장치가 Source 가 되어 입력 데이터가 흘러가구요.
데이터의 최종 목적지는 프로세스가 됩니다.
간략한 흐름은 아래와 같습니다.
1. 키보드 입력
2. Keyboard Controller 에 해당하는 디바이스 컨트롤러가 키보드의 입력 신호를 수신함.
3. Interrupt 가 발생하고, CPU 는 키보드의 입력 정보를 우선적으로 처리하게 됨.
4. 키보드 입력 정보는 Standard Input 으로 추가됨.
5. 현재 활성화 되어있는 프로그램 (ex. 웹 브라우저, 워드 프로세서 등등) 이 해당 키보드의 입력을 수신하여 처리함.
해당 과정에서 Device Controller 와 Interrupt 등 하드웨어적인 개념들이 적용됩니다.
키보드로 타이핑한 정보들이 Keyboard Controller 에 저장되구요.
Keyboard Controller 는 Interrupt 를 발생시켜서 키보드 입력을 최우선적으로 처리하게 합니다.
처리된 키보드 입력 정보는 표준 입력으로 추가되고,
Activated Process 가 해당 데이터를 최종적으로 수신하게 됩니다.
pipe input.
pipeline (|) 과 redirection (>) 는 프로세스의 Standard Input 과 Standard Output 를 사용합니다.
아래의 경우가 대표적인 케이스인데요.
ls | grep test
ls 와 grep 명령어는 하나의 실행 파일을 실행시키는 명령어이구요.
ls 프로세스의 실행 결과가 표준 출력으로 출력됩니다.
ls 프로세스는 디렉토리의 파일명을 리스팅하는 명령어입니다.
그리고 grep 은 표준입력으로 입력받은 텍스트 중에서 첫번째 인자인 test 를 포함하는 텍스트를 필터링하는 명령어입니다.
요약하자면,
ls -> "파일명1", "파일명2", "파일명3", ... -> Standard Output
"파일명1", "파일명2", "파일명3", ... -> Standard Input -> grep (필터링함.)
와 같은 구조가 됩니다.
ls 는 표준 출력으로 데이터를 내보내고, grep 은 표준 입력으로 입력된 데이터를 읽어들입니다.
Pipe 는 프로세스의 표준 출력과 프로세스의 표준 입력을 연결하는 기능입니다.
File Input.
File 도 표준입력의 입력 데이터가 될 수 있습니다.
바이너리 파일의 경우에는 줄바꿈이 명확하지 않아서 표준 입력으로 사용하기가 살짝 애매하지만,
텍스트 파일 같은 경우에는 줄바꿈이 명확하여 표준 입력의 입력 데이터로 사용됩니다.
예를 들어보겠습니다.
<number.txt>
1 2 3 4 5 6 7 8 9
<read_stdin.py>
import sys while True: text = sys.stdin.readline() print(text) if text == '' or text is None: break;
<Redirection 실행>
표준입력을 읽어들이는 Python 프로그램을 실행하며,
Redirection 방식으로 number.txt 를 입력 데이터로 사용합니다.
python3 read_stdin.py < number.txt
<실행 결과>
1 2 3 4 5 6 7 8 9
File Descriptor.
File Descriptor 는 운영체제가 사용하는 File 의 식별값입니다.
모든 파일이 File Descriptor 를 가지진 않구요.
Open 되어있는 File 에 한해서 File Descriptor 를 가집니다.
그 중에서도
- standard input (File Descriptor : 1)
- standard output (File Descriptor : 2)
- standard error (File Descriptor : 3)
위 세가지는 고정적인 File Descriptor 를 가지고,
모든 프로세스는 File Descriptor 로써 1, 2, 3 번 File Descriptor 를 가지게 됩니다.
테스트.
동기화 테스트.
여러 프로세스가 동시에 표준 입력을 read 하면 어떻게 될까?
아래 코드를 실행하여 엄청나게 긴 number.txt 을 생성합니다.
for i in {1..1000000}; do echo "$i" >> number.txt done
그리고 나서 read_stdin 프로세스를 실행합니다.
여러 터미널을 열어서 read_stdin 프로세스를 동시에 진행해야합니다.
python3 read_stdin.py < number.txt
실행 결과는 별다른 동기화 이슈없이 잘 처리됩니다.
그 이유는 Standard Input 이 하나만 존재하긴 하지만, 운영체제 레벨에서 프로세스 별로 표준 입력을 위한 버퍼를 생성한다고 합니다.
즉, 프로세스별로 버퍼가 생성이 되니 동기화 이슈없이 표준입력을 사용할 수 있습니다.
반응형'System' 카테고리의 다른 글
RPC (Remote Procedure Call) 알아보기 (0) 2023.10.14 IPC Signal 알아보기 (0) 2023.10.07 Shared memory communication 알아보기 (0) 2023.10.07 [memory management] page 알아보기 (0) 2023.09.22 Call Stack 이해하기 (0) 2023.09.21