강좌

HOME > 강좌 >
강좌| 리눅스 및 오픈소스에 관련된 강좌를 보실 수 있습니다.
 
Step By Step 커널 프로그래밍 강좌 ①
조회 : 25,631  


Step By Step 커널 프로그래밍 강좌

커널프로그래밍의환경구축

 

 

강좌는 커널 프로그래밍에 관심을 가지고 있는 입문자들을 위한 것이다. 하지만 아무리 입문자라고 해도 리눅스에 대해 전혀 모르고 있다면 강좌를 이해하기 쉽지 않을 것이다. 따라서 글을 보고 있는 독자라면 리눅스에서 Application 프로그래밍을 이상 해봤다는 가정 아래 강좌를 진행하고자 한다. 구체적으로 말하자면 gcc vi 정도는 사용할 있으며

기본적인 리눅스 명령어들을 알고 있는 분들을 말한다. 커널 프로그래밍 회에서는 커널 프로그래밍을 하기 위한 환경구축및 커널 패치하기, 커널 프로그래밍의 특징 등에 대해 살펴보도록 한다.

 

_ 민찬 KLDP 멤버, 전문 프로그래머

 

 

앞으로의 연재 순서

커널 프로그래밍의 환경 구축

모듈 구현하기

커널의 동기화에 관하여

커널의 시간관리 지연 함수에 대하여

파일시스템과 proc file system 사용하기

디버깅 기술에 관하여

 

 

커널 프로그래밍 개발환경 구축

5~6 전만 해도 리눅스 커널을 적절하게 다시 빌드하는 것은 그리 만만한 작업이 아니었다. 하지만 요즘의 리눅스 배포판들은 굉장히 쉬운 방법으로 리눅스 커널을 빌드할 있게 했다. 심지어는 그것을 패키지 형태로 만들어 다른 컴퓨터에 복사함으로써 단순한 설치명령어를 실행하는 것만으로도 리눅스 커널을 설치할 있도록 하고 있다.

여기서 필자는 커널 프로그래밍의 환경 구축을 위해 현재 리눅스 데스크탑용으로 가장 인기를 끌고 있는 우분투(ubuntuedgy) 6.10 desktop 용을 사용할 것이다. 우분투는 iso 이미지 형태로 다음의 URL 페이지에서 다운로드할 있다 (http://releases.ubuntu.com/6.10/

ftp://ftp.kaist.ac.kr/ubuntu-cd/edgy/). 우분투를 설치하는 것은 윈도우를 설치하는 것만큼이나 쉽다. 심지어는 윈도우와 멀티 부팅 환경도 스스로 만들어 준다.

우리가 해야 것은 ISO image CD 만들어서 설치하면 그만이다. 또는 필자와 같이 vmware 같은 툴을 활용하면 ISO파일을 그대로 이용해 윈도우에서 설치할 수도 있다. 우분

투에 관한 내용들은 다음의 URL 많은 정보들이 있다. ( http://www.ubuntu.or.kr/wiki.php/FrontPage)

우분투의 설치가 끝났다면 기본적으로 일반 사용자로 로그인이 되어 있을 것이다. 커널 컴파일을 위해서는 root 사용자의 권한이 필요하다. sudo 명령을 사용하여 커널을 빌드할 수도

있지만 쉽게 하기 위해 root 로그인을 다시 하도록 한다. root로의 login 다음의 명령을 통해 있다.

 

 

sudo i

 

우분투 6.10에는 기본적으로 /bin/sh /bin/dash 심볼릭링크로 되어 있다. 이것으로 인하여 소스를 컴파일 하는데 간혹 문제가 생기는 같다. 다음의 명령을 통해 /bin/bash

사용할 있게 바꾼다

 

rm f /bin/sh

ln s /bin/bash /bin/sh

 

 

다음으로 apt-get 이용하여 현재 시스템의 모든 패키지들

최신으로 update한다.

 

apt-get update

 

이번에는 자신이 현재 사용하고 있는 커널의 버전을 확인해

보자. 커널 버전은 다음의 명령을 통해 확인해 있다.

 

 

uname r

 

 

아마도 우분투 6.10이나 이하의 버전을 사용하고 있는

자중 직접 커널을 업데이트하지 않은 독자라면 현재 2.6.17-

10 버전 이하의 리눅스 커널을 사용하고 있을 것이다.

 

 

리눅스 커널 버전 관리

2.6.18 = major.minor.release

 

 

2.6.18이라하면 major번호가 2이고 minor 6, 그리고 18번째라는 것이다. , 2.6 18번째 릴리즈된 버전이라는 . 또한 리눅스의 minor 버전은 커널이 안정된 버전인지 개발

버전인지를 나타낸다. 안정된 버전은 짝수를 가지며 개발중인 버전은 홀수를 갖게 된다. 일반적으로 짝수와 홀수 버전은 커널 아카이브 트리에 공존한다.

예를 들어 2.4 짝수 minor 버전을 가진 새로운 커널이 릴리즈되면 2.5 홀수 버전을 가진 개발버전이 2.6 준비하며작업에 들어간다. 2.5에서 개발 중인 개발 버전들이 많은

추가와 테스트를 통해 안정화되면 2.4 릴리즈 버전들이 점차 올라가며 2.5 기능들이 추가되고 버그들이 수정되어 나간다. 2.4.1, 2.4.2, 2.4.3 이런 식으로 올라가게 되는

이다. 현재는 우리가 사용하고 있는 커널의 minor 번호는 6 이니 안정된 버전이라고 있다.

하지만 2.6으로 오면서 변화가 생겼다. 2.6대의 커널이 릴리즈되면 2.7 2.8 준비해야 하는 커널 아카이브 트리가 생겨야 하지만 현재 그렇지가 않다. 2004 Linux Kernel

Developer Summit에서 이상 그런 개발방법으로 진행하지 않기로 결정했기 때문이다. 2.6커널은 충분히 안정화되어 있고 홀수 버전을 만들어야 만큼 기능변화가 없을 것이

라는 판단에서이다. 지금부터 우리는 현재 커널을 2.6.18 버전으로 업그레이드

것이다. 먼저 시스템에 커널을 빌드하고, 빌드된 커널을 데비안 패키지로 만들기 위한 툴들을 설치해야 한다. 콘솔에서 다음 명령을 통해 그러한 툴들을 설치할 있다.

 

 

apt-get install kernel-package

libncurses5-dev fakeroot

wget bzip2

 

 

이번엔 우리가 빌드하게 2.6.18버젼의 커널 소스를 다운로드 하도록 하자. 우리는 wget 사용할 것이다. 하지만 wget install되어 있지 않은 분들은 웹브라우저를 통해서도 아래

URL에서 다운로드할 있다.

 

 

cd /usr/src

wgethttp://www.kernel.org/pub/linux/kernel/v2.6/

linux 2.6.18.tar.bz2

 

 

이것으로 커널의 빌드를 위한 환경구축은 끝마쳤다.

 

 

 

커널 빌드

이번에는 다운로드 받은 새로운 커널을 빌드하기 위해

/usr/src 디렉토리에 압축을 해지한 linux 이름으로 심볼

링크를 만든 새로운 커널의 소스 디렉토리로 이동한다.

 

 

tar xjf linux-2.6.18.tar.bz2

ln -s linux-2.6.18 linux

cd /usr/src/linux

 

지금부터는 커널 컴파일에 앞서 자신의 시스템 환경에 맞게 커널을 설정하는 과정이다. 사실 커널 빌드를 위해 설정하는 과정이 커널 빌드에 있어 제일 복잡하고 어려운 과정이다.

냐하면 자신의 시스템의 모든 하드웨어와 하드웨어 연결관계를 모두 알고 있어야 하기 때문이다. 또한 하드웨어와 관련된 커널 설정들도 일일이 설정해줘야 자신의 시스템에

가장 알맞은 형태의 커널을 구성할 있다.

하지만 이러한 모든 지식을 갖기 위해서는 많이 시간을 투자해야 한다. 대부분의 배포판에는 위와 같은 설정을 가지고 있는 파일이 이미 있다. 물론 자신의 시스템에 최적화된 config

파일은 아니다. 단지 일반적으로 사용할 있는 config 파일일 뿐이다. 그러므로 불필요한 설정을 포함하고 있는 경우도 많이 있다. 하지만 강좌를 쉽게 만들기 위해 우리는 배포판에

이미 있는 config 파일을 사용하도록 것이다. config파일을 자신의 환경에 최적화할 있게 불필요한 것은 빼서 날씬하게 만드는 일은 여러분들의 몫이다. ( 오래되긴 했지

다음의 글을 보면 많은 도움이 것이다.

http://kldp.org/KoreanDoc/html/Kernel-KLDP/)

 

 

 

커널을 빌드할 사용되는 kbuild config파일을 통해 커널설정을 하게 된다. config 파일을 만드는 방법은 크게 3가지가 있다.

 

 

 

make config : 텍스트를 기반으로 사용자가 질문에

대하여 대답하는 방식

make menuconfig : 텍스트 기반 curses 라이브러리

사용하는 방식

make xconfig : X윈도우 기반의 방식

 

 

우리는 방식 make menuconfig 사용할 것이다. 먼저 아래의 명령을 통해 현재 디렉토리 /usr/src/linux 배포판의 config 파일을 .config라는 이름으로 복사하도록 하자.

(다른 배포판들도 이와 유사한 config 파일을 /boot 디렉토리나 커널 소스에 설치했다면 /usr/src/config 등에 들어 있을 것이다.)

 

 

cp /boot/config-`uname r` ./.config

 

 

이번에는 복사된 .config 파일을 커널 설정에 반영할 차례이다. make menuconfig 통해 .config 파일을 읽어 들인다. 먼저 Load an Alternate Configuration File 항목으로 들어

간다.

 

 

 

이번에는 .config 파일을 입력하여 .config파일을 읽어 들인다.

 

 

마지막으로 설정을 저장하고 빠져나온다.

 

이제 커널을 빌드할 차례이다. 우분투에서는 컴파일을 때 다음과 같은 방법을 통해 우분투 패키지로 커널 이미지와 커널 헤더파일을 만들어 내는 것을 권장한다. 현재는 계속

/usr/src/linux 디렉토리다.

 

make-kpkg clean

make-kpkg --initrd --append-to-version=

-barrios kernel_image kernel_headers

 

 

make-kpkg clean 과정은 처음으로 커널 소스의 압축을 풀어 새롭게 빌드를 시작하는 경우에는 필요하지 않은 과정이 다. 명령을 수행하게 되면 커널 소스 디렉토리에 있는 이전

빌드했던 오브젝트 파일들을 제거한다. 다음으로 append-to-version 들어갈 내용은 항상 -(하이픈 부호) 시작해야하며 어떤 공백도 들어가선 된다. 이름은 커널을 구분짓기 위한 이름이니 자신이 생각해서 알맞은 이름으로 넣으면 된다. 커널의 빌드과정이 끝나게 되면

/usr/src 디렉토리에는 다음과 같은 2개의 .deb 패키지 형태의 결과물이 나오게 된다.

 

 

linux-image-2.6.18-barrios_2.6.18-barrios-

10.00.Custom_i386.deb

linux-headers-2.6.18-barrios_2.6.18-barrios-

10.00.Custom_i386.deb

 

 

번째 파일은 실제 커널 이미지를 포함하고 있는 파일로서 이 파일을 설치하면 커널이 시스템에 설치되는 것이다. 번째 파일은 나중에 모듈만 새로 추가할 필요한 커널

파일을 설치하는 것이다. 파일을 아래와 같은 명령으로 설치할 있다.

dpkg i linux-image-2.6.18-barrios_2.6.18-

barrios-10.00.Custom_i386.deb

dpkg i linux-headers-2.6.18-barrios_2.6.18-

barrios-10.00.Custom_i386.deb

 

이제 새로운 커널의 설치가 끝났다. 정말 간단하지 않은 가? 재부팅을 커널 버전을 확인해보자.

 

커널 설치 후의 변화들

우리는 위에서 만든 커널의 설치로 인해 우리의 시스템에는

어떤 변화가 있어났는지를 알아야 필요가 있다. 그래야만

우분투가 아닌 다른 시스템에서도 커널 업그레이드를 진행할

있을 것이다. 사실 패키지 형태로 커널을 설치할 때는

빌드에 필요한 다음과 같은 과정을 건너 있다. 일반적

으로 커널을 빌드할 때는 다음의 명령어 순으로 진행하기

련이다.

 

 

일반적인 커널 빌드 절차

make clean

make

make modules_install

cp arch/i386/boot/bzImage /boot/vmlinuz-2.6.18-barrios

cp System.map /boot/System.map-2.6.18-barrios

cd /boot

mkinitramfs 2.6.18-barrioso /boot/initrd.img-2.6.18-barrios

 

 

/boot 디렉토리를 살펴보면다음과 같은 파일들이 생긴 것을 알 있다.

 

config-2.6.18-barrios : 새로운 커널의 config 파일

initrd.img-2.6.18-barrios : 새로운 커널이 사용하게 될 initramfs 파일

System.map-2.6.18-barrios : 새로운 커널의 커널 함수들의 주소가 저장되어 있는 파일(나중에 디버깅을 위해 사용됨)

vmlinuz-2.6.18-barrios : 새로운 커널의 압축 이미지가 들어있는 바이너리

 

 

또한 /lib/modeuls 디렉토리에는 다음과 같은 디렉토리가 생겨 것을 있다. 일반적인 컴파일 방법으로는 make modules_install 실행하면 생성되는 디렉토리이다.

2.6.18-barrios : 새로운 커널의 모듈들이 들어있는 디렉토리

 

 

마지막으로 /boot/grub/menu.lst에는 다음과 같은 항목이 추가된 것을 있다.

 

 

title Ubuntu, kernel 2.6.18-barrios

root (hd0,0)

kernel /boot/vmlinuz-2.6.18-barrios

root=/dev/sda1 ro quiet splash

initrd /boot/initrd.img-2.6.18-barrios

quiet

savedefault

boot

title Ubuntu, kernel 2.6.18-barrios

(recovery mode)

root (hd0,0)

kernel /boot/vmlinuz-2.6.18-

barrios root=/dev/sda1 ro single

initrd /boot/initrd.img-2.6.18-barriosboot

 

 

이들은 새로운 커널로 부팅할 있도록 grub(부트로더)에게 알리는 역할을 한다.

 

 

커널 패치하기

다음으로 우리는 커널 패치(Patch) 대해서 알아보도록 한다. 커널 개발자들은 커널의 새로운 기능이나 버그들을 패치파일의 형태로 만들어서 전달한다. 그렇기 때문에 자신의 커널을 업그레이드(새로운 기능을 추가, 기존의 버그 해결)하기 위해서는 커널을 패치하는 방법에

대해 알고 있어야 한다. 패치를 하기위해서는 기본적으로 patch라는 명령을 사용한

. patch 명령을 사용하는 방법은 간단하다. patch 명령에 리다이렉션을 이용해 입력으로 패치 파일을 주면 된다. 우리는 현재 2.6.18 커널 버전에서 2.6.19-rc4 우리의

널을 업그레이드해볼 것이다. 커널 업그레이드를 위해 prepatch 파일을 사용할 것이다.

 

 

prepatch?

prepatch 리눅스 커널의 업데이트를 위한 알파 버전이라고 보면 된다. 안정적인 버전이 릴리즈되기 여러 개발자들에게 테스트를 부탁하는 커널 버전이다. 그래서 시간이 흘러 버그들이

보고되고 수정되면 새로운 안정적인(Stable) 버전이 나오게 되는 것이다.

파일들은 리눅스 커널의 archive testing 디렉토리에 존재한다. (http://www.kernel.org/pub/linux/kernel/v2.6/testing/) prepatch 파일을 적용하는 데는 규칙이 있다. prepatch 파일의 이전 버전의 fullrelease 커널에 적용해야 한다는 것이다. prepatch-2.6.19-rc3 라면 linux-kernel 2.6.18 적용해야 한다는 것이다. 2.6.18.1이나 2.6.18.2 같은 커널에 적용해서는 된다. rc Release Candidate 약자로써 Linux Tovalds 의해 릴리즈 후보가 것이다.

 

 

다음의 명령을 통해 패치 파일을 다운로드할 있다.

 

cd /usr/src

wget http://www.kernel.org/pub/linux/kerne

/v2.6/testing/patch-2.6.19-rc6.b

 

다운로드가 끝났다면 이번에는 다시 우리의 커널 소스 디렉토리로 이동해 다음 명령을 통해 패치파일이 이상 없이 적용가능한지 확인해 보고 이상이 없으면 실제로 패치파일을 적용한다.

 

cd /usr/src/linux

bzip2 dc /usr/src/patch-2.6.19-rc6.bz2 |

patch -p1 dry-run

bzip2 dc /usr/src/patch-2.6.19-rc6.bz2 |

patch -p1

 

번째 명령은 실제로 패치파일을 적용하는 것은 아니다. 단지 실제로 하는 것처럼 수행해보고 이상 유무를 보고할 뿐이다. 패치를 이상 없이 끝마쳤다면 위의 커널 빌드 과정을 반복하여 다시 커널을 설치해보자.

 

 

커널 프로그래밍의 특징

지금까지 우리는 커널 프로그래밍에 앞서 커널을 새로 빌드하는 방법, 커널에 패치를 적용하는 방법들을 살펴보았다. 마지막으로 우리는 실제 커널 프로그래밍에 들어가기에 앞서 커널프로그래밍이 일반 응용 어플리케이션 프로그래밍과 다른 , 그리고 커널 프로그래밍을 시작하려는 독자들을 위해 몇몇웹사이트들을 소개하며 이번 강좌를 마무리 지려고 한다.

일반적으로 커널 프로그래밍은 어렵다고 생각한다. 그렇게 생각하는 것일까? 당연히 커널 프로그래밍을 하기 위해서는 리눅스 커널에 관한 많은 지식들을 가지고 있어야만 한다.

어도 자신이 지금 하려는 것이 커널의 어떤 서브 컴포넌트들과 어떤 인터페이스들을 통해 동작하는지 정확히 이해하고 있어야만 한다. 하지만 이러한 것들은 지금 커널 프로그래밍

입문하는 사람들에게는 별로 닿지 않을 것이다. 이러한 문제들은 프로젝트를 진행하며 점차 커널에 관한 지식을 쌓아가며 또는 사전에 충분한 스터디를 통해 해결해야

문제들이다. 그러한 문제들은 결코 시간에 해결할 있는 문제가 아니라는 것이다. 그보다 먼저 부딪히는 문제들은 다음과 같다.

첫째, 라이브러리와 시스템콜을 사용할 없다. 처음 입문하는 커널 프로그래머들에게 가장 먼저 다가오는 괴로움은 응용프로그래밍에서와 같이 많은 라이브러리와 시스템콜(System

Call) 등을 사용할 없다는 것이다. 예를 들어 커널에서 어떤 file 만들고 싶다면 어떻게 것인가? 응용 프로그램들처럼 open 시스템콜을 사용할 것인가? 물론 불가능하다.

둘째, 커널이 죽는다면 어떻게 디버깅을 것인가? 커널에는 fault 나면 그것을 해결해 만한 화려한 도구가 있지 않다. 임베디드 환경은 더욱 그렇다. 그나마도 없지만 x86

스템에서 동작하는 커널 디버깅 툴들이 대부분 arm이나 mips 등의 임베디드 환경에서는 동작하지 않는 경우가 많다. 그래서 대부분 커널 개발자들은 printk 같은 원시적인 방법

의존하고 있는 것이 사실이다. 하지만 x86환경에서는 보다 좋은 툴들이 가지 있다.

셋째, 커널은 한정된 스택 사이즈를 갖는다. 일반 응용 프로그램들은 동적으로 증가될 있는 스택을 갖는다(물론 한계는있다). 반면, 커널은 기본적으로 8K 스택을 갖는다. 또한

적으로 커질 수도 없다. 하지만 현재 x86에서는 8K 너무 커서, 스택 사이즈를 4K 줄이는 패치가 들어가 있다. 그러므로 커널 프로그래밍에서는 절대적으로 스택을 아껴서 사용해

한다. 게다가 커널 스택은 자신만이 사용하는 것이 아니다. 커널의 여러 Kernel Control Path에서 프로세스의 스택을 공유하여 사용할 있으므로, 특정 Path에서 너무 많은 스택

사용하게 되면 나중에 사용하게 Path에서는 이상 사용할 있는 공간이 남아 있지 않게 된다. 문제에 대해서는 나중에 소개할 기회가 있을 것이다. 기억해야 것은스택은

절대 4K 이상 넘어갈 없다. 또한 내가 사용하는 스택은 나 혼자만 쓰는 것이 아니다라는 점이다. 넷째로, 커널에는 메모리 보호장치가 없다는 것이다. 응용

로그램은 리눅스의 MMU(Memory Managet Unit) 이용한 가상 페이지 할당방식으로 인해 절대 다른 프로세스의 주소를 침범할 없다. 또한 자신의 주소 공간에서도 금지된(illegal)

주소 공간을 침범하게 되면 커널은 error 잡아내고 프로세스에게 신호(Signal) 전달한다.

신호에 대해서 대비하여 놓지 않은 일반 프로세스들은 Segment Fault 일으키며 죽게 된다. 다른 프로세스들은 절대 영향을 받지 않으며 자신들만의 주소공간에서 안정적으로

실행되고 있을 것이다. 하지만 커널 프로그래밍은 상황이 전혀 다르다. 커널이 금지된(illegal) 메모리 주소에 접근하게 되면 결과는 Oops라는 형태로 나타나게 된다. Oops 인하여 커널이 죽게 되면 시스템이 다운되는 것이다. 이것은 어떤 환경에서도 용납될 없는 문제이다. 마치 윈도의 블루스크린과 같다

 

 

필자 김민찬 씨는 운영체제에 많은 관심을 갖고 연구해 왔으며 현재는 kldp.org(리눅스 한글 문서화 프로젝트) 멤버로 활동하며, 리눅스 커널과 glibc 관련된 개발 업무를 담당하고 있다.

 

 

출처 : 공개 SW 리포트 7호 페이지 52 ~ 57 발췌(2007 6) - 한국소프트웨어 진흥원 공개SW사업팀 발간

 

 


[원글링크] : https://www.linux.co.kr/home2/board/subbs/board.php?bo_table=lecture&wr_id=1639


이 글을 트위터로 보내기 이 글을 페이스북으로 보내기 이 글을 미투데이로 보내기

 
한국소프트웨어진흥원 공개SW사업팀