메뉴

문서정보

JoinC와 함께하는 리눅스 시스템 프로그래밍 2장 시작하기

목차

소개

시스템 프로그래밍이란 시스템 프로그램을 작성하기 위한 일련의 과정을 의미한다. 시스템 프로그램은 시스템을 제어하는 프로그램이므로 결국 시스템 프로그래밍은 시스템을 알아가는 과정이라고 볼 수 있을 것이다.

시스템을 알아가는 과정이라고 해서, 컴퓨터의 CPU, Memory, 하드디스크등의 시스템 자체에 대해서 공부할 필요는 없으니 미리 겁을 먹을 필요는 없다. 앞장에서 설명했듯이 운영체제(:12)가 제공하는 함수를 통해서, 시스템에 간접적으로 접근할 수 있기 때문이다.

운영체제 덕분에 우리는 컴퓨터 시스템에 대한 대략적인 이해를 하고 있는 정도로도 컴퓨터 시스템을 다룰 수 있다. 물론 여러분이 임베디드(:12)환경에서 작동하는 프로그램을 만들어야 한다면 컴퓨터 시스템에 대한 좀더 깊은 지식이 필요로 하겠지만, 대게의 경우 운영체제를 통한 간접적인 지식만으로도 시스템 프로그램을 작성하는데 문제가 생기는 경우는 없을 것이다.

운영체제와 커널

운영체제는 컴퓨터를 운용하는 특별한 종류의 프로그램이다. 이 운영체제는 핵심이라고 할 수 있는 부분이 있는데, 이것을 커널이라고 한다. 커널은 컴퓨터 시스템을 제어하는 일, 그러니까 메모리를 관리하고, 디스크에 데이터를 읽고쓰고, 프로그램을 실행시키고, 네트워크 카드, 사운드카드, 그래픽카드등의 하드웨어 장치를 관리하는 일을 한다.

학문적인 관점에서 보자면 운영체제란 바로 이 커널을 가리키는 것이다. 예를 들어 리눅스 운영체제는 리눅스 커널을 의미한다. 하지만 커널만을 가지고 할 수 있는 일은 그렇게 많지 않다. 커널위에 shell(:12), 운영자 관리도구와 같은 필수적인 다른 프로그램이 있어야 비로서 컴퓨터를 제어할만한 환경이 갖추어진다.

이런이유로 일반적인 관점에서 커널 + 필수 프로그램까지를 운영체제라고 부르고 있다.

다음 그림은 컴퓨터 시스템 과 커널, 프로그램의 관계를 보여주고 있다.

attachment:systemprograming.png

Kernel space와 User space

이렇게 커널이 할 수 있는 영역과 일반 응용 프로그램이 할 수 있는 영역이 구분이 되어 있다. 응용 프로그램은 직접적으로 시스템에 도달할 수 없으며, 리눅스 커널에 요청을 하는 방식으로 간접적으로 시스템을 제어할 수 있다.

이때 커널이 다루는 영역을 Kernel space라고 하고, 일반 응용 프로그램이 다루는 영역을 User space라고 한다.

커널 스페이스와 유저 스페이스가 나뉘는 가장 큰 이유는 보안상의 문제다. 아무 프로그램이나 시스템자원을 직접 제어할 수 있다면, 심각한 문제가 발생할 수 있기 때문이다. 하드웨어와 프로그램의 중간에 리눅스 커널이 존재함으로써, 시스템 자원을 안전하고 효율적으로 사용할 수 있게 해준다.

응용 프로그램은 절대로 시스템에 바로 접근할 수 없다.

응용 프로그램

운영체제를 제외한 프로그램, 즉 운영체제위에서 작동하는 모든 프로그램을 응용 프로그램이라고 한다. 시스템 프로그램과 네트워크 프로그램 혹은 게임프로그램등 모든 프로그램이 응용 프로그램이다.

응용 프로그램이 실행되면, 시스템콜(:12)을 이용해서 운영체제에게로 부터 컴퓨터 시스템의 자원의 사용을 요청하는 방식으로 원하는 작업을 수행하게 된다. 예를 들어 주소록을 저장하는 프로그램은 키보드를 사용할 수 있도록 커널에게 요청해서 사용자 입력을 받아들이고, 받아들인 입력을 임시로 저장하기 위해서 메모리공간을 요청하고, 영구히 저장하기 위해서 디스크를 요청하는 과정을 거쳐서 주어진일을 하게 될 것이다.

시스템콜과 라이브러리

시스템콜이란 운영체제에게 요청할 수 있도록 만들어진 함수임을 알수 있을 것이다. 이런 이유로 시스템콜은 종종 시스템 함수라고 부르기도 한다. 리눅스 운영체제는 대략 190개 정도의 시스템콜을 제공한다. 시스템콜에 대한 자세한 목록은 Linux System Call Table문서를 참고하기 바란다. 시스템콜은 운영체제마다 다르기 때문에 만약 윈도우즈에서 프로그래밍하기를 원한다면, 그에 맞는 시스템콜 목록이 필요하다.

기본적으로는 시스템콜만을 이용하는 것으로도 어떠한 프로그램이든지 만들어낼 수 있기는 하다. 그러나 시스템콜만을 이용해서 프로그램을 작성하는건 보통 어려운일이 아니다. 시스템콜만을 가지고도 이미지를 읽어서 화면에 출력하는 프로그램을 작성할 수는 있기는 할 것이다. 하지만 개발에 너무 많은 시간이 걸리기 때문에 시스템콜만을 가지고 개발하지는 않는다. 보통은 이미 만들어진 이미지 제어를 위한 함수를 사용해서 개발을 하게 된다.

이렇게 함수를 만들고, 용도에 맞게 모아놓은 것을 라이브러리(:12)라고 한다. 함수모음집이라고 할 수 있을 것이다. 예컨데, 그래픽라이브러리, 수학라이브러리, 와 같은것들이다. 몇개의 함수만 모아놓은 간단한 라이브러리 부터, 돈을받고 판매하는 상업용 라이브러리까지 폭넓게 존재한다.

리눅스 운영체제

우리가 다루고자 하는 운영체제인 리눅스는 유닉스계보에서 비교적 최근에 생겨난 운영체제다. 몇몇 리눅스 신봉자들은 리눅스를 유닉스계보에 집어 넣는 것에 대해서 불쾌하게 생각하는 것 같기는 하지만, 이 문서에서는 리눅스가 명백하게 Unix계보에 속하는 운영체제라고 정의할 것이다.

리눅스 운영체제는 커널필수 프로그램으로 이루어지며 일반적으로 배포판을 리눅스 운영체제라고 간주한다. 배포판은 리눅스를 쉽게 설치하고 관리할 수 있도록 커널, 관리 프로그램, 필수 응용 프로그램을 패키징 한거라고 보면 된다. 패키징 방법에 따라서 다양한 배포판이 존재하는데, RedHat(:12), Ubuntu(:12)와 같은 것들이 널리 사용되는 배포판이다.

이 문서는 여러분이 리눅스 운영체제를 어느정도 사용할 줄 안다고 가정하고 만들어졌으머로 설치와 명령어의 사용과 같은 내용을 다루진 않을 것이다. 이하 리눅스 운영체제의 시스템영역에서의 상세한 내용은 시스템 프로그래밍을 진행하면서 조금씩 익혀나가도록 하겠다.

만약 리눅스 시스템에 대한 기본적인 내용을 알기를 원한다면 리눅스 환경에서의 C 프로그래밍 2장 문서를 참고하기 바란다.

리눅스 커널 구조

리눅스 운영체제의 핵심인 커널은 다음과 같은 구조를 가진다.

이미지 참고 : 리눅스 시스템 프로그래밍 고영웅

프로세스는 프로그램의 실행이미지로 프로그래밍된데로 필요한 일을 수행한다. 리눅스 커널은 user space와 kernel space가 분리되어 있다. 그러므로 user space의 프로세스는 직접 하드웨어 자원이나 기타 커널에서 제공하는 (IPC 와 같은) 서비스를 사용할 수없다. 대신 system call을 이용해서 커널에 요청을 할 수 있다. 커널에서 제공하는 요청 인터페이스 이다. 프로세스는 시스템 콜을 이용해서 커널에 필요한 작업을 요청할 수 있다. device driver를 이용해서 각종 장치들을 제어하고, 프로세스를 스케쥴링하고 메모리를 관리한다. 또한 프로세스간 통신을 위한 IPC(:12)를 제공한다. 컴퓨터 하드웨어는 다양한 device(장치)들로 구성이 된다. 커널은 이러한 device를 제어해야 한다. 이러한 device 를 제어하는 단위코드를 device driver이라고 한다.

리눅스 도움말 시스템

도움말시스템은 일반사용자와 개발자를 막론하고 중요한 요소중 하나다. 윈도우즈 같은 경우에는 MSDN이라는 도움말 시스템을 제공한다. 개발자는 프로그램을 작성하는 도중에 모르는 함수나 기술적인 사항이 있다면, 온라인 혹은 오프라인상에서 매우 상세한 도움말을 얻을 수 있다.

운영체제가 성공을 하기 위해서는 개발자를 끌어들일 수 있어야 한다. 개발자를 끌어들이는 가장 좋은 방법은 좋은 개발 툴을 제공하는 것과 좋은 도움말 시스템을 제공하는 것이다. 이런 이유로 MS, Apple, IBM, HP, SUN 등의 회사들은 전략적으로 좋은 도움말 시스템을 제공하기 위해서 노력한다.

유닉스 운영체제는 man page라는 도움말 시스템을 제공한다. 개발자는 다음과 같은 방법으로 함수나 명령어들에 대한 도움을 얻을 수 있다.
# man sprintf
리눅스 역시 유닉스와 동일한 man page 제공한다. man page에 대한 자세한 내용은 man 도움말 문서를 참고하기 바란다.

리눅스 표준 라이브러리

리눅스는 자주 사용되는 기능을 구현한 표준 라이브러리 함수를 제공한다. 이 라이브러리에는 간단한 수학연산, 문자열의 변환, 문자열 입출력, 병렬처리, 파일제어등을 손쉽게 할 수 있도록 도와주는 함수를 제공한다.

이들 함수를 시스템콜만을 이용해서 직접 만든다고 한다면 짧게는 100라인에서 길게는 수천라인까지 작성을 해야 하겠지만 표준 라이브러리 함수를 이용하면 몇줄내에서 해결할 수 있다.

리눅스 시스템 프로그래밍은 시스템콜표준 라이브러리함수를 이용한 프로그래밍영역이라고 보면 된다. 나머지는 응용 프로그래밍 영역으로, 시스템콜과 표준라이브러리에 덧붙여 다른 광범위한 영역의 라이브러리들을 사용하게 된다.

예컨데, 게임을 만들고자 한다면 시스템 프로그래밍과 관련된 함수들외에 그래픽, 사운드, 이벤트 관련 라이브러리들을 사용하게 될 것이다.

리눅스 표준라이브러리에서 제공하는 함수들은 표준라이브러리 man page를 참고하기 바란다. 그냥 참고만하도록 하자. 굳이 익힐려고 노력할 필요없다. 문서를 읽어나가다 보면 자연스럽게 익히게 될 것이다.