개발자가 알아야 하는 OS와 하드웨어의 기초
본사에서 출장 온 사원과 점심을 먹으러 자주 가던 분식점에 들렀다. 나는 안 먹어 봤었던 카레덮밥을 그는 오므라이스를 시켰다. 오므라이스는 자주 먹어 봤었는데, 나에겐 양이 꽤 많았다. 하지만 카레덮밥은 카레가 비비지 않은 채 나왔는데, 양이 더 많았다.
밥을 다 먹고, 옆의 카페에 들려 말하기를, 알고 보니 카레덮밥으로 나오는 볶음밥과 오므라이스의 계란 안의 볶음밥이 똑같다는 거였고, 사원이 거들기를 김치볶음밥의 볶음밥도 똑같았다는 거였다. 그러니깐 분식점은 모든 덮밥류의 밥(OS, Operating System)은 공통적으로 들어가는 재료(디바이스 드라이버)로 볶는 거였고, 그 위에 뭐가 덮이느냐(Interface, 접속기)에 따라서 명칭과 가격만 달라질 뿐이었다.
굉장히 효율적인 메뉴 관리였다. 카운터의 사장님은 항상 김밥만 말고 식당에서는 정식류만 준비해서 나가면 되는 거였다. 효율적인 인출 관리로 김밥만 실시간으로 말아서 카운터에서 손님에게 바로 전달해주면 되는 구조다. 어쨌든 다음번에 오므라이스, 카레덮밥, 김치덮밥을 동시에 시키더라도 음식이 나오는 타이밍은 똑같을는지 테스트해보고 싶었다.
컴퓨터에서 윈도나 리눅스가 필요한 연유도 식당에의 운영(operating) 원리와 같은 체계(system)다. 일반적으로 여러 가지 프로그램을 프로세스라고 하는 단위로 실행한다. 여기서 실행의 주체는 운영체제(operating system)인데, 리눅스를 포함하여 대부분의 OS는 여러 개의 프로세스를 동시에 실행할 수 있다(다케우치, 2019).
운영체제, 즉 리눅스나 윈도가 필요한 연유는 하드웨어와의 관계에서 비롯되었다. 설명을 위해 리눅스와 하드웨어의 관계에 대해 국한하여 이유를 들자면(간단히 설명하고자 리눅스와 OS를 크게 구별 짓지 않는다면), 리눅스의 중요한 역할은 외부 장치(이하 디바이스)를 조작하는 일이다. 리눅스와 같은 OS가 없으면 여러 개의 프로세스가 각각 디바이스를 조작하는 코드를 작성해야 한다(다케우치, 2019).
위의 도식처럼 OS가 없어도 동작은 하겠지만 다음과 같은 단점들이 있다.
모든 애플리케이션 개발자가 디바이스의 스펙을 상세히 알아야만 디바이스를 조작할 수 있다.
개별 개발이므로 개발 비용이 커짐
멀티 프로세스가 동시에 디바이스를 조작할 경우 예상외의 동작을 발생시킬 수 있다.
도입부에서 사례로 말한 식당밥에서 운영체제에 해당하는 볶음밥이 없다면, 요리사가 개별 메뉴(오므라이스, 카레덮밥, 김치볶음밥)의 요리법을 상세히 알아야만 손님에게 음식을 만들어서 전달할 수 있다.
또한 덮밥류에 공통으로 들어갈 수 있는 볶음밥을 각 메뉴별로 각각 다르게 요리해야 할 수도 있으므로 요리사의 요리시간과 투입에너지가 커지므로 소모비용이 커진다.
마지막으로 위의 세 가지 메뉴가 동시에 주문으로 들어올 경우에는 볶음밥을 할지, 덮밥을 위한 백미만을 준비해야 할지, 아니면 들어갈 재료를 어떻게 배분해야 할지 혼동스러워서 시간이 지체될 수도 있다.
이러한 단점 때문에 앞서 말한 분식점에서의 운영원리와 같이 리눅스는 '디바이스 드라이버(볶음밥)'라고 하는 프로그램을 통해 디바이스를 다룬다. 따라서 아래와 같이 디바이스(장치) 드라이버를 통해서만 디바이스를 조작할 수 있다(다케우치, 2019).
만약, 디바이스 드라이버가 아닌 프로그램의 버그나 해킹 목적으로 특정 프로세스가 위의 룰('장치 드라이버를 통해 장치에 접근함')을 깨면 다중 프로세스가 동시에 디바이스를 조작하려고 시도하는 상황이 발생한다(해킹 용어로 '레이스 컨디셔닝(Race Conditioning)'이라고 하는 공격으로 여러 개의 프로세스가 동시에 경합하는 조건을 일컫는다.).
리눅스는 이러한 문제를 피하고자 CPU에 있는 기능을 이용하여 프로세스('주체')가 직접 하드웨어('개체')에 접근하는 것을 차단한다. CPU에는 커널 모드와 사용자 모드라는 두 가지 모드가 있으며 커널 모드로 동작할 때만 디바이스에 접근할 수 있다. 디바이스 드라이버는 커널 모드로 동작하고 프로세스는 사용자 모드로 동작한다(다케우치, 2019).
식당에서 주문(프로세스) 받은 메뉴(디바이스)를 내놓기 위해 '디바이스 드라이버'라는 공통된 볶음밥을 미리 준비해놓으면 효율적으로 디바이스를 관리할 수 있을 뿐만 아니라, 일반적인 프로세스로 실행하면 문제가 되는 처리(수행)가 몇 가지 있다. 예를 들면 다음과 같다.
프로세스 관리 시스템 → 카운터 주문 호출
프로세스 스케쥴링 → 김밥 예약받고 미리 싸놓음
메모리 관리 시스템 → 정식류와 김밥류를 분리해서 주문받고 내놓음
이러한 처리도 커널 모드(주문 이후의 카운터에서 수행과정)에서 동작한다. 이렇게 커널 모드에서 동작하는 OS의 핵심 부분이 되는 처리를 모아 담당하는 프로그램을 '커널'(식당 주인, 관리자)이라고 부른다. 프로세스(손님의 주문)가 디바이스 드라이버에 포함한 커널(식당 관리자)이 제공하는 기능(볶음밥에 공통적으로 들어가는 재료)을 사용하려 할 때는 '시스템 콜'이라고 하는 특수한 처리를 통해 커널에 요청한다. 또한 OS(볶음밥)는 커널(볶는 재료)만을 지칭하지 않는다. 커널 외에도 사용자 모드에서 동작하는 다양한 프로그램으로 구성되어 있다(다케우치, 2019).
다음 편에서 그렇다면, 리눅스의 사용자(유저, 손님) 모드에서 동작하는 OS 기능 및 프로세스 그리고 커널과의 인터페이스(접점, 카운터)가 되는 시스템 콜에 대해서 설명하겠다.
참조('최고의 리눅스 커널 입문서', 왜 이제 두 번 볼까...)
0) 다케우치 시토루. (2019). 실습과 그림으로 배우는 리눅스 구조 (pp. 46-47). n.p.: 한빛미디어.