난이도 : 초급 Darrick Addison, 소프트웨어 엔지니어/컨설턴트, ASC Technologies Inc
2001 년 8 월 01 일 Darrick Addison은 임베디드 리눅스 애플리케이션과 환경을 검토한다. 애플리케이션을 개발하는데 있어서 적합한 하드웨어 및 소프트웨어 환경을 설정하는 방법을 설명한다.
리눅스는 애플리케이션의 범위를 확장해나가고 있다. IBM이 선보인 리눅스 손목시계 부터, 핸드헬드 (PDA와 휴대폰), 정보
가전, 씬 클라이언트(thin client), 방화벽, 산업용 로봇, 전화통신 기반 장비, 클러스터 기반 수퍼컴퓨터 까지 이르렀다.
임베디드 시스템으로서 리눅스가 해야 할 일에 대해 생각해 보자.
임베디드 시스템의 등장
장비를 제어하는 데 사용되는 컴퓨터(임베디드 시스템)는 컴퓨터 그 자체 만큼이나 친숙하다. 60년대 후반, 전화 스위치를 제어하는
통신에 사용되었던 것이 최초의 임베디드 시스템으로 알려져 있다. 지난 몇 십년 동안 컴퓨터는 소형화 되었다. 임베디드 시스템도
그러한 추세를 따라갔다. 외형은 작아졌지만 더 많은 기능을 제공한다. 네트워크와 연결할 필요성이 대두되면서 네트워킹 스택도 필요해졌다.
더욱 복잡해 졌고 더 많은 메모리와 인터페이스가 필요하게 되었다. OS의 서비스에 대한 기대도 높아졌다.
임베디드 시스템용 OS는 70년대 후반에 등장했다. 요즘은 십 여 가지의 제품이 있다. 이 중에서 VxWorks, pSOS,
Neculeus, Windows CE 등이 주요 제품으로 등장했다.
임베디드 시스템으로서
리눅스의 장/단점
대부분의 리눅스 시스템이 PC 플랫폼에서 운용되고 있다. 리눅스는 임베디드 시스템에서도 믿을 수 있는 성능을 발휘할 수 있다.
리눅스의 접근 방식인 "기본으로 돌아가자 (back-to-basics)"는 Unix 보다 훨씬 쉽고 유연한 설치 및 관리 환경을
제공할 수 있게 되었다. 기존의 UNIX와 비슷한 명령어와 프로그래밍 인터페이스를 가지고 있기 때문에 UNIX 사용자들에게도
더욱 친숙하다.
일반적인 리눅스 시스템은 PC에서 실행할 수 있도록 패키지화 되었다. 하드 디스크와 메모리가 패키지 되었다. 대부분은 임베디드
시스템에는 필요하지 않은 것들이다. 완벽한 기능을 갖춘 리눅스 커널은 1 MB의 메모리를 필요로 한다. 반면 리눅스 마이크로
커널은 실제로 Pentium CPU에서 100 K만을 소비한다. 이것은 가상 메모리와 모든 핵심 OS 기능을 포함한 것이다.
네트워킹 스택과 기본 유틸리티를 갖춘 완벽한 리눅스 시스템은 Intel 386 microprocessor상에서 500 K 메모리(8-bit
bus (SX))로 훌륭하게 실행된다. 필요한 메모리는 웹 서버나 SNMP agent 등의 애플리케이션 필요에 의해 결정되기
때문에, 리눅스 시스템은 256 KB ROM과 512 KB RAM처럼 작은 용량에도 적용된다. 때문에 임베디드 시장에는 갈 수
있는 경량 OS가 필요하다.
기존의 RTOS (real-time operating system)보다 임베디드 리눅스 같은 오픈 소스 OS를 사용할 때의
이점 중 하나는, 리눅스 개발 커뮤니티는 새로운 IP와 프로토콜을 RTOS 벤더보다 빠르게 지원한다는 점이다. 예를 들어, network
interface card (NIC) 드라이버나 직/병렬 포트 드라이버와 같은 디바이스 드라이버의 경우 상용 OS보다 리눅스에서
훨씬 더 많이 사용할 수 있다.
 |
플래시 메모리 (flash memory)
Flash RAM 은 특별한 메모리이다. 대부분의 Palm 디바이스는 OS를 저장하는 데 있어서 이것을
사용한다. OS를 업그레이드 할 수 있는 이점이 있고 디지털 핸드폰, 디지털 카메라, LAN 스위치, PC 카드,
디지털 셋톱 박스, 임베디드 콘트롤러 등의 소형 디바이스에 사용된다. 임베디드 리눅스 같은 임베디드 시스템은 디스크
드라이브가 필요하지 않다. 다시 말해서, 리눅스가 플래시 메모리를 다 써버리면, 추가 프로그램이나 정적 데이터를 저장하기
위해서 읽기 전용 파일시스템으로서 플래시 메모리의 일부를 사용한다.
|
|
핵심 리눅스 OS는 매우 단순한 마이크로커널(micro-kernel) 아키텍쳐이다. 네트워킹과 파일시스템은 마이크로 커널의
상단에 놓이게 된다. 드라이버와 다른 기능들은 컴파일 되거나 로드가 가능한 모듈로서 런타임 시 커널에 추가된다. 이것은 임베디드
시스템을 구현하는 데 있어서 모듈식의 빌딩블록(building-block)을 제공한다.
임베디드 시스템에는 또한 종종 일반적인 주변기기와 애플리케이션인 프로그램과 드라이버와 같은 기본적인 기능도 구현되어야 한다.
바퀴를 다시 만들지 않기 위해서 이다. 리눅스는 광범위한 주변기기와 대부분의 마이크로프로세서 상에서 실행될 수 있다.
리눅스는 임베디드 인터넷 디바이스에 적당하다. 마이크로프로세서 시스템을 지원하기 때문이다. 이 기능은 디자이너에게 실시간 애플리케이션을
이중 프로세서 시스템에서 실행할 수 있는 옵션을 제공한다. 전체 프로세싱 파워를 증가시킨다. 그래서 다른 프로세스에서 GUI를
실행하면서 동시에 한 프로세스에서는 리눅스 시스템을 실행할 수 있는 것이다.
임베디드 시스템에서 리눅스를 실행할 때의 단점은 리눅스 아키텍쳐가 커널 공간에서 실행되는 실시간 소프트웨어 모듈의 추가를 통해서
실시간 퍼포먼스를 제공한다는 것이다. 커널 공간은 스케줄링, 하드웨어-인터럽트 예외처리, 프로그램 실행 등을 구현하는 OS의
부분이다. 이러한 실시간 소프트웨어 모듈이 커널 공간에서 실행되기 때문에 코드에러는 전체 시스템의 신뢰도에 영향을 끼칠 수 있다.
반면 RTOS 같은 경우 실시간 퍼포먼스를 위해 완전히 새로 디자인되었다. 시스템 레벨 프로세스에 반하는 사용자에 의해 시작되었을
때 다른 것보다 특정 프로세스에 높은 우선순위를 할당함으로써 신뢰도를 높인다. 프로세스는 메모리나 하드 드라이브에서 실행하는
프로그램으로서 OS에 의해 구분된다. process ID 또는 숫자 식별자를 할당 받아서 OS가 현재 실행되고 있는 프로그램과
관련 우선순위 레벨을 지속적으로 트래킹 할 수 있도록 한다. 그와 같은 접근방식으로 RTOS의 신뢰도 (predictability)를
보장할 수 있다.
소프트웨어 및 하드웨어
요구사항
다양한 유저 인터페이스 툴과 프로그램 때문에 리눅스의 기본 커널은 다양해질 필요가 있다. 여기에서는 메모리 관리를 갖춘 "stripped-down"
에서 완벽한 파일시스템과 네트워크 서비스를 지원하는 서버에 이르기까지, 광범위한 영역으로 리눅스를 생각해 보자.
임베디드 리눅스 시스템에는 적어도 다음의 세 가지가 필요하다:
- boot utility
- 메모리 관리, 프로세스 관리, 타이밍 서비스로 이루어진 리눅스 마이크로 커널
- 초기화 프로세스
추가 사항으로 다음을 고려해 보는 것도 좋다:
- 하드웨어용 드라이버
- 필요한 기능을 제공하기 위한 한 개 이상의 애플리케이션 프로세스
다음의 요구사항들도 고려해야 한다:
- 파일시스템 (ROM 또는 RAM에 존재)
- TCP/IP 네트워크 스택
- semi-transient 데이터와 스왑 기능을 저장하는데 필요한 디스크
- 32-bit internal CPU (모든 Linux 시스템에 요구됨)
ThinLinux
|
하드웨어 프로젝트
다음은 현재 진행되고 있는 리눅스용 임베디드 하드웨어 프로젝트이다.
PLEB
: Pocket Linux Embedded Box with ARM SA-1100
/ ArmLinux Ucsimm / Uclinux Flash EPROM.
Linux Lab
: 이 프로젝트는 리눅스 용 데이터 콜렉션(data collection)
및 프로세스 제어 소프트웨어 개발자를 위한 프로젝트이다. 하드웨어 지원에서 애플리케이션 개발에 이르기까지, 다양한
애플리케이션을 위한 표준 개발 환경을 제공하고자 기획되었다.
Controller Area Network
: Linux GPIB용 Controller
Area Network (CAN) 버스 드라이버; Linux GPIB Package는 GPIB (IEEE 488.1)
하드웨어용 지원 패키지이다. 드라이버는 National Instruments AT-GPIB, TNT488.2, PCII
& PCIIa 보드를 지원한다.
|
하드웨어 플랫폼 옵션
최고의 하드웨어를 선택하는 것은 복잡한 일이 될 수 있다. 회사 내부의 정책, 편견, 다른 프로젝트의 유산, 정확한 정보 부족,
비용 등이 문제가 되기 때문이다. 가끔씩, 빠르고 저렴한 CPU도 일단 다른 주변기기와 작동하는 데 필수적인 버스 로직과 지연
문제 등이 고려 될 때 비싸진다. 프로젝트를 위해 필요한 CPU 속도를 계산하기 위해서는 주어진 태스크를 수행하고 태스크를 세
배로 만들기 위해서 CPU가 얼마나 빨라야 하는지를 현실적으로 판단하는 것이 우선 수행되어야 할 과제이다. 또한, 버스가 얼마나
빨리 실행되어야 하는지를 결정해야 한다. PCI 버스 같은 2차적인 버스가 있다면 그것들 역시 고려해야 한다. 느린 버스 (DMA
트래픽으로 포화 된 버스)는 빠른 CPU를 현격하게 정체 시킬 수 있다. 다음은 임베디드 리눅스 애플리케이션을 위한 최상의 하드웨어
솔루션이다.
실시간 임베디드 리눅스
애플리케이션
임베디드 시스템과 관련하여 가장 중요한 문제 중 하나는 실시간 OS에 대한 필요이다. 여기에서 말하는 실시간이라는 개념은 약간
다르다. 어떤 사람에게 있어서 실시간이란 1 마이크로 초 범위 이내에 이벤트에 반응하는 것을 의미한다. 또 어떤 사람에게는 50
밀리초(millisecond)를 의미한다. 어떤 시스템은 이벤트에 대해서 짧은 반응 레이턴시를 필요로 한다. 하지만 대부분의
시스템의 경우 자세하게 분석해 보면 실제로 실시간에 가까운 반응 시간이 필요함을 알 수 있다. 일반적으로 이러한 시스템의 디자인에
대해서 자세히 살펴본다면 드라이버의 인터럽트와 애플리케이션은 실시간 필요사항을 충족시키기 위해서 신중하게 디자인되어야 한다는
결론이 나올 것이다.
RT-리눅스에는 인터럽트 핸들링에 대해 정밀한 제어를 제공하는 시간에 민감한 함수를 포함하고 있다. 인터럽트 메니저를 사용한다.
필요할 경우 중요한 인터럽트가 실행될 수 있도록 한다. 이러한 접근방식에 있어 난점은 대부분 CPU 인터럽트 구조와 콘테스트
변환 하드웨어 지원에 의존한다는 점이다. Real-time Extension이 없더라도, 리눅스는 이벤트의 다중 스트림을 매우
잘 따라간다. 예를 들어, 저급 Pentium상의 리눅스 PC system은 다중 10BaseT 인터페이스를 효과적으로 실행한다.
동시에 어떤 데이터도 손실하지 않고 56KBPS에서 "character-level" 시리얼 포트를 실행한다.
고려해 볼 만한 실시간 하드웨어 및 소프트웨어 리눅스 API는 RT리눅스, RTAI, EL, 리눅스-SRT 등이 있다. RT리눅스는
New Mexico Institute of Technology에서 개발한 실시간 리눅스 API 이다. RTAI (DIAPM)는
RT리눅스 real-time API에서 나왔다. EL/IX는 POSIX 기반의 실시간 리눅스 API이다. 리눅스-SRT는 real-time
API의 대안이다. 프로그램을 변경하거나 재컴파일 하지 않고도 모든 리눅스 프로그램에 향상된 기능을 제공할 수 있다.
참고자료 에서 자세한 정보를 참조하기 바란다.
구성 절차
네트워크와 X server를 제공하는 소형의 리눅스 배포판을 만드는 방법을 살펴보자. 이 배포판을 다운로드 할 수 있다. 자신만의
임베디드 리눅스 시스템을 구현하려면 유틸리티, 소스, 컴파일러, 디버거, 문서 등이 포함된 완전한 리눅스 배포판이 필요하다.
다음은 LEM을 만드는데 사용될 수 있는 소프트웨어 리스트이다:
자세한 사항은 참고자료를 참조하기 바란다.
부트 디스크 만들기
- bootdisk는 기본적으로 플로피 디스켓 상의 소형의 self-contained 리눅스 시스템이다. 완전한 리눅스의 기능 대부분을
수행할 수 있다. 다음은 Bootdisk-HOWTO (참고자료)를 기초한 드. 부트로더는 커널을 찾아 메모리에 로드한 후 실행시키는 방식으로
부트를 시작.
- 리눅스 등과 같은 운영체제 커널의 시작 부분.
리눅스 커널이 디스켓에 직접 복사된 경우(raw copy)라면 디스크의 첫 번째 섹터는 리눅스 커널 그 자체의 첫번째 섹터가
된다. 이 첫번째 섹터는 부트 디바이스로부터 커널의 나머지 부분을 계속 읽어서 부트 프로세스를 진행한다.
Step 2. 부트 로더
부팅 프로세스를 실행하기 위해 LILO와 같은 부트 로더를 사용하게 될 것이다. 이것은 같은 하드웨어 상에 공존하기 위해 개발
및 생산 플랫폼이 같은 하드웨어 상에 공존할 수 있도록 한다. 재부팅에 의해서 하나에서 다른 것으로 변환을 허용한다. LILO
부트 로더는 bios에 의해 로딩된다. 그런 다음 이것은 커널이나 다른 OS의 부트 섹터를 로딩한다. 또한 옵션을 사용하여 아이템을
상호적으로 선택할 수 있도록 간단한 명령행 인터페이스를 제공한다. LILO 관련 자세한 사항은 참고자료를
참고하기 바란다.
Step 7. 새로운 파티션 만들기
LFS-HOWTO (참고자료): 새로운 리눅스 시스템을 구현하기 전에, 새로운 시스템을
구현할 수 있는 비어있는 리눅스 파티션이 필요하다. 리눅스 전용의 파티션을 이미 가지고 있다면, 이번 단계를 건너 뛰어도 된다.
옵션으로서 적절한 하드 디스크를 이용하여 fdisk (또는 cfdisk) 프로그램을 시작한다. 리눅스 전용 파티션을 만들고,
파티션 테이블을 작성하고, (c)fdisk 프로그램을 종료한다. 파티션 데이블이 업데이트 되었는지를 확인하기 위해 시스템을 재부팅
시켜야 한다는 메시지를 받으면 시스템을 재부팅 한다.
Step 8. 새로운 파티션에 ext2 파일시스템 만들기
LFS-HOWTO (참고자료): 새로운 ext2 파일시스템을 만들기 위해서 mke2fs
명령어를 사용한다. 유일한 옵션으로 $LFS를 주면 파일 시스템이 만들어질 것이다. 지금부터 나는 새롭게 만들어진 파티션을 $EMBPART
라고 부르겠다.
Step 9. 파티션 마운트하기
mkdir /mnt/hda?
mount $EMBPART /mnt/hda?
|
/dev/hda4 에 파티션을 만들었다면 이것을 /mnt/hda4에 마운트 한다. 그런 다음, $dollar;EMBPART/usr/sbin에
파일을 복사했던 단계로 돌아가서 그 파일을 /mnt/hda4/usr/bin에 복사한다. Step 14의 마지막 명령어 다음에
이것을 수행한다 ( $EMBPART/usr/sbin에 파일을 복사한다).
Step 10. 파일시스템 설치하기
루트 파일시스템은 완전한 리눅스 시스템을 지원하는 데 필요한 모든 것을 포함하고 있어야 한다. File Hierarchy Standard
(참고자료)에서 많이 벗어나지 않는 디렉토리 구조를 구현할 것이다.
TinyLogin과
login dependencies 설치하기
TinyLogin (참고자료)는 다음의 35Kb이하의 툴을 제공한다:
/bin/addgroup, /bin/adduser, /bin/delgroup, /bin/deluser, /bin/login,
/bin/su, /sbin/getty, /sbin/sulogin, /usr/bin/passwd.
명령어와 관련한 자세한 설명은 주요 배포판의 문서 또는 man page를 참조한다.
- Sysvinit 아카이브를 푼다.
- src 디렉토리로 간다.
- $EMBPART/sbin의 init 실행파일을 복사한다.
Sysvinit 패키지는 contrib 디렉토리에 C 버전의 start-stop-daemon을 제공한다.
- 이것을 컴파일 한다.
- $EMBPART/usr/sbin에 있는 파일을 복사한다.
Listing 1. Inittab 설정 스크립트
# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.6 1997/01/30 15:03:55 miquels Exp $
# Modified for LEM 2/99 by Sebastien HUET
# default rl.
id:2:initdefault:
# first except in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
# single-user mode.
~~:S:wait:/sbin/sulogin
# /etc/init.d executes the S and K scripts upon change
# 0:halt 1:single-user 2-5:multi-user (5 may be X with xdm or other) 6:reboot.
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# CTRL-ALT-DEL pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -r now
# Action on special keypress (ALT-UpArrow).
kb::kbrequest:/bin/echo "Keyboard Request--edit /etc/inittab to let this work."
# /sbin/mingetty invocations for runlevels.
1:2345:respawn:/sbin/getty 9600 tty1
2:23:respawn:/sbin/getty 9600 tty2
#3:23:respawn:/sbin/getty tty3 #you may add console there
#4:23:respawn:/sbin/getty tty4
|
Listing 2. 디렉토리와 베이스 파일을 만드는 스크립트
cd $EMBPART/etc
mkdir rc0.d rc1.d rc2.d rc3.d rc4.d rc5.d rc6.d init.d rcS.d rc.boot
|
패킹이 풀린 Sysvinit 소스 디렉토리로 간다.
debian/etc/init.d/rc을 :$EMBART/etc/init.d에 복사한다.
$EMBPART/etc/init.d/로 간다.
LEM에서와 마찬가지로 새로운 파일인 rcS를 만든다:
Listing 3. RCS 스크립트
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
/etc/default/rcS
export VERBOSE
# Trap CTRL-C only in this shell so we can interrupt subprocesses.
trap ":" 2 3 20
# Call all parts in order.
for i in /etc/rcS.d/S??*
do
[ ! -f "$i" ] && continue
case "$i" in
*.sh)
(
trap - 2 3 20
. $i start
)
;;
*)
$i start
;;
esac
done
# run the files in /etc/rc.boot
[ -d /etc/rc.boot ] && run-parts /etc/rc.boot
|
distro의 run-parts를 $EMBPART/bin에 복사한다.
Listing 4. comment line
<!-reboot---------------------------------------------->
|
다음과 같은 것을 포함하고 있는 새로운 file reboot을 만든다:
Listing 5. Reboot 스크립트
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
echo -n "Rebooting... "
reboot -d -f -i
<!-halt---------------------------------------------->
|
다음과 같은 새로운 file halt를 만든다:
Listing 6. Halt 스크립트
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
halt -d -f -i -p
<!-mountfs---------------------------------------------->
|
요약
리눅스는 정보 가전에서 전문적 제어 시스템에 이르기까지, 임베디드 애플리케이션 분야에 전망이 밝다. 약 95%의 마이크로컴퓨터
칩이 임베디드 애플리케이션에 사용된다. 리눅스의 신뢰성, 유연성, 확장성은 마이크로프로세서 아키텍쳐, 하드웨어 디바이스, 그래픽
지원, 통신 프로토콜 등의 지원에 힘입어 점점 대중적인 소프트웨어 플랫폼으로 자리 매김 해가고 있다.
리눅스는 오픈 소스이기 때문에, 리눅스의 구성과 지원 소프트웨어 컴포넌트는 시장과 애플리케이션의 다양한 요구에 부응하여 끊임없이
진화하고 있다!
참고자료
필자소개  | | Darrick Addison은 ASC Technologies Inc의 소프트웨어 엔지니어 겸 컨설턴트이다. 1993년 부터 다양한 환경에서, 네트워크
애플리케이션(TCP/IP client/server), GUI 애플리케이션, 임베디드 시스템 애플리케이션에 이르는 소프트
웨어 개발을 해왔다. Johns Hopkins 대학에서 컴퓨터 공학을 전공했다. |
기사에 대한 평가
|