리눅스 Tips, 리눅스 C/C++ 프로그래밍, 모바일 클라우드 동향 및 테스트 등

2012년 11월 27일 화요일

리눅스 시스템 프로그래밍 : 02 시스템 프로그래밍의 시작


1. 소개

 시스템 프로그래밍이란 시스템 프로그램을 작성하기 위한 일련의 과정을 의미한다. 시스템 프로그램은 시스템을 제어하는 프로그램이므로 결국 시스템 프로그래밍은 시스템을 알아가는 과정이라고 볼 수 있을 것이다. 시스템을 알아가는 과정이라고 해서, 컴퓨터의 CPU, Memory, 하드디스크 등의 시스템 자체에 대해서 공부할 필요는 없으니 미리 겁을 먹을 필요는 없다. 앞 장에서 설명했던 것처럼 운영체제가 제공하는 함수를 통해서, 시스템에 간접적으로 접근할 수 있기 때문이다.

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

2. 운영체제와 커널

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

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

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


  • Linux Kernel은 컴퓨터 시스템의 자원을 직접 제어한다.
  • 프로그래머가 작성한 프로그램은 직접 시스템 자원을 제어할 수는 없다.
  • 프로그램은 커널에서 제공하는 함수를 이용해서 간접적으로 시스템 자원을 제어한다.

  2.1 Kernel space와 User space

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

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

  2.2 응용 프로그램

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

  2.3 시스템 콜과 라이브러리

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

 기본적으로는 시스템 콜만을 이용하는 것으로도 어떠한 프로그램이든지 만들어낼 수 있기는 하다. 그러나 시스템 콜만을 이용해서 프로그램을 작성하는 것은 보통 어려운 일이 아니다. 시스템 콜만을 가지고도 이미지를 읽어서 화면에 출력하는 프로그램을 작성할 수는 있기는 할 것이다. 하지만 개발에 너무 많은 시간이 걸리기 때문에 시스템 콜만을 가지고 개발하지는 않는다. 보통은 이미 만들어진 이미지 제어를 위한 함수를 사용해서 개발을 하게 된다. 이렇게 함수를 만들고, 용도에 맞게 모아 놓은 것을 라이브러리라고 한다. 함수 모음집이라고 할 수 있을 것이다. 이러한 라이브러리에는 그래픽 라이브러리, 수학 라이브러리 등 여러 종류가 있으며, 몇 개의 함수만 모아 놓은 간단한 라이브러리부터, 돈을 받고 판매하는 상업용 라이브러리까지 폭넓게 존재한다.

3. 리눅스 운영체제

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

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

  3.1 리눅스 커널 구조

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

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

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

  3.2 리눅스 도움말 시스템

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

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

 유닉스 운영체제는 'man page'라는 도움말 시스템을 제공한다. 개발자는 다음과 같은 방법으로 함수나 명령어들에 대한 도움을 얻을 수 있다.

# man sprintf
 
 리눅스 역시 유닉스와 동일한 man page 제공한다. man page에 대한 자세한 내용은 man 도움말 문서를 참고하기 바란다.

  3.3 리눅스 표준 라이브러리

 리눅스는 자주 사용되는 기능을 구현한 표준 라이브러리 함수를 제공한다. 이 라이브러리에는 간단한 수학 연산, 문자열의 변환, 문자열 입출력, 병렬 처리, 파일 제어 등을 손쉽게 할 수 있도록 도와주는 함수를 제공한다. 이들 함수를 시스템 콜만을 이용해서 직접 만든다고 한다면 짧게는 100라인에서 길게는 수 천 라인까지 작성을 해야 하겠지만 표준 라이브러리 함수를 이용하면 몇 줄 내에서 해결할 수 있다.

 리눅스 시스템 프로그래밍은 시스템 콜과 표준 라이브러리 함수를 이용한 프로그래밍 영역이라고 보면 된다. 나머지는 응용 프로그래밍 영역으로, 시스템 콜과 표준 라이브러리에 덧붙여 다른 광범위한 영역의 라이브러리들을 사용하게 된다. 예를 들어, 게임을 만들고자 한다면 시스템 프로그래밍과 관련된 함수들외에 그래픽, 사운드, 이벤트 관련 라이브러리들을 사용하게 될 것이다.

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

댓글 1개:

  1. 출처 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/system_programing/Book_LSP/Ch02_Beginning

    답글삭제