불친절한 C++ 노트는 작성자가 C++을 복습한 내용을 적은 것이며, 학부생 수준의 운영체제(리눅스)나 컴퓨터 구조 관점에서 C++을 바라봅니다.
Hello, World! |
프로그래머란 직업은 참으로 겸손합니다.
무엇이든 처음보는 상대를 마주하면 인사부터 하기 때문이죠.
- Hello, World!
- Hello, C++!
- Hello, Web Server!
그 중에서 "Hello, World!"는 가장 일반적이고 간단한 인사법으로 유명하지만,
안에 숨겨진 내부적인 동작원리는 결코 간단하지 않습니다.
아래의 단순한 프로그램이 얼마나 복잡한 매커니즘 위에서 움직이는지,
차분하게 알아보도록 합시다.
Standard Streams |
스트림(Stream)이란 입출력 대상과의 추상화된 데이터 흐름(Abstracted Data Flow)이며,
통신방법(How data is communicated)이 추상화된 데이터 통신을 의미합니다.
데이터를 전송하기 위해 모든 일련의 전송과정을 제어하는 대신,
전송과정을 추상화하여 데이터에만 집중하자는 것이죠.
데이터가 움직이는 방향에 따라 입력 스트림과 출력 스트림으로 나뉘지만.
데이터의 방향이 다른 것 뿐이지 근본적인 차이는 없습니다.
데이터 송신자
데이터 수신자
데이터 채널
OS는 프로세스가 만들어지면 3개의 통신채널(Communication Channels)을 생성하는데,
각각 표준 입력/표준 출력/표준 에러라고 부르며, 묶어서 표준 스트림(Standard Streams)이라고 합니다.
우리는 이 표준 스트림을 통해 키보드와 디스플레이와 통신할 수 있는데,
표준 스트림은 터미널 키보드, 터미널 디스플레이와의 I/O를 추상화한 통신채널이기 때문입니다.
Standard Streams are NOT Unique |
이것을 이용하면 외부에서 콘솔의 I/O 동작에 관여가 가능하고,
Raw Input |
그렇다면 실제 키보드(Real Keyboard)의 데이터는 어떻게 터미널 키보드(Terminal Keyboard)로 전송될까?
먼저 입력장치에 대해 알아볼 필요가 있습니다.
데이터를 생성하여 컴퓨터에게 제공하는 주변장치를 입력장치라고 하며,
사람이 쉽게 사용할 수 있다는 의미로 HIDs(Human Interface Devices) 라고 합니다.
예를 들면 아래와 같은 장치들이 되겠죠.
키보드, 마우스, 터치스크린
조이스틱, 컨트롤러
마이크
하지만 곧바로 입력장치를 사용할 수 없습니다.
유닉스에서는 입력장치를 사용하기 위해서는 아래 2가지의 모듈이 필요합니다.
드라이버
핸들러
- Pooling
- Interrupt
- 1) 시스템상 특수키인지 검사한다. (예를들면, 윈도우에서 Ctrl + Alt + Delete)
- 2) 프로그램상 특수키인지 검사한다. (예를들면, 크롬 브라우저에서 Ctrl + F)
- 3) 여기까지 왔다면, 포커싱된 프로세스의 표준 입력으로 넘긴다.
만약 포커싱된 프로세스가 표준 입력을 받을 수 없는 상황이라면 해당 데이터는 무시됩니다.
이 때, 입출력장치에서 바로 가져온 데이터를 Raw Input이라고 하는데,
다음과 같은 정보가 포함되어 있습니다.
데이터를 발생시킨 장치의 정보
데이터가 발생된 시간 (Time-Stamp)
데이터 타입 (KEY_PRESS, KEY_RELEASE, KEY_REPEAT)
데이터 값
연결된 입력장치를 OPEN 하면 Raw Input을 얻어올 수 있습니다.
즉, Raw Input을 사용하면 포커싱되지 않은 상황에서도 키보드의 입력을 얻어올 수 있습니다.
민감한 주제이므로 루트권한이 필요합니다.
참고자료 |
Stack Exchange # How to view the output of a running process in another bash session?
How stuff works # From the Keyboard to the Computer
Linux Kernal Document # Input Interface
컴퓨터 시스템 구조 3rd Edition (M. Morris Mano, 김종상 역) # 입출력과 인터럽트