Mobile

[안드로이드] (2)시스템과 리눅스

OSS 2012-09-12 14:40:20 27138
임베디드월드

글: 라영호 | ratharn@naver.com / 2012-03-05


[연재 차례]

1. 안드로이드 시스템의 역사 및 동향
2. 안드로이드 시스템과 리눅스
3. 안드로이드 플랫폼의 이해
4. 안드로이드 바인더(Binder)의 이해
5. 안드로이드 서비스
6. 안드로이드 SurfaceFlinger와 프레임버퍼 드라이버
7. 안드로이드 User Interface와 ADK2012
8. Linux Sound Device와 안드로이드 사운드 시스템
9. 안드로이드 카메라 시스템
10. 안드로이드 카메라와 멀티미디어 프레임워크
11. 안드로이드 카메라와 멀티미디어 프레임워크 ②
12. 안드로이드 시스템 디버깅 및 기타





안드로이드 시스템 개발자를 위한 안드로이드 시스템의 분석 및 이해 ②
안드로이드 시스템과 리눅스

안드로이드, 리눅스 그리고 시작과 끝
안드로이드 시스템의 가장 큰 특징은 자바를 기반으로 운영되는 시스템이지만 그 근간에는 리눅스라는 든든한 운영체제가 버티고 있다. 과거 임베디드 리눅스를 이용하여 시스템을 개발하는 많은 시도들이 있었지만, 플랫폼이 가져야 할 여러 가지 요소들 즉, 응용 프로그램을 개발하기 위한 개발 환경과 같은 에코 시스템(Eco-system)의 부족으로 인해 사장되었다. 하지만 구글이라는 든든한 주체가 있는 안드로이드 시스템은 리눅스의 장점과 에코 시스템을 구축하기 위한 지속적인 노력으로 인해 지금의 안드로이드가 모바일 운영체제의 중심으로 우뚝 설수 있게 된 것이다. 물론 여러 가지 넘어야 할 산은 아직 많다. 또한 아직 부족한 점도 많다. 하지만, 오픈 소스의 장점을 통해 그 단점과 극복해야 할 문제점들은 점차 개선될 것이다.

안드로이드의 구조
안드로이드 시스템의 전체적인 구조는 [그림1]과 같이 구성되었다.


[그림 1]


(1) 리눅스 커널
안드로이드에 맞게 수정된 리눅스 커널이다. 따라서, 리눅스 운영체제가 가지고 있는 기본적인 기능들을 가지고 있으며 여기에 안드로이드 시스템이 동작을 하기 필요한 기능들이 추가된 형태로 구성되어 있다. 하드웨어를 구동하기 위한 디바이스 드라이버, 메모리 관리, 프로세스 관리, 네트워크 관리등과 같은 운영체제의 기본 역할을 담당한다.

안드로이드를 위해 수정된 내용은 기존의 리눅스 운영체제와 달리 모바일 운영체제로써 안드로이드 시스템이 동작하기에 필요한 기능들이 포함되어 있다.

안드로이드 시스템을 위해 리눅스 커널에 추가된 내용
Alarm : Android.app.AlarmManager, 정해진 시간에 지정된 작업과 이벤트를 발생할 수 있도록 기능 제공

Low Memory Killer : 흔히, LMK라고 약자를 사용하고 안드로이드 시스템 동작 중 메모리 부족 상태에 메모리를 확보하기 위해 사용하는 커널 드라이버

Ashmem : Android(Anonymous) Shared Memory Driver, 즉, 안드로이드 시스템에서 사용하는 리소스 및 데이터를 시스템상의 공유 메모리 공간을 통하여 이용을 하기 위해 제공하는 공유 메모리 관리자




Low Memory Killer의 동작 구조



Android System의 리소스(Resource)부족 시 동작 프로세스 그룹당 우선순위를 주어, 우선순위가 낮은 그룹의 프로세스를 한꺼번에 해제, 메모리 부족 시 프로세스들을 강제로 종료시키는 역할을 한다.


Kernel Debugger/Logger : 안드로이드 시스템에서 발생하는 로그 메시지를 관리하는 드라이버, 흔히 안드로이드 Logcat 유틸리티를 사용하여 시스템 정보 및 메시지를 파악하기 위해 이용되는 드라이버다.

Binder : 바인더 드라이버는 안드로이드 시스템에서 핵심적인 역할을 하고 안드로이드에서 제공하는 모든 프레임웍들의 기능을 이용하기 위해 사용되는 드라이버다. 물론 바인더 기능은 매우 복잡하며 단순히 드라이버라기 보다, 안드로이드 시스템에서 독립된 프로세서로 구현된 서비스의 기능을 호출하고, 호출된 결과를 전달하기 위한 메커니즘으로 사용된다. 프로세서간 통신, 즉, IPC(Inter-Process Communication) 방법을 사용하고 있다. 하지만 바인더 드라이버는 단순히 바인더 드라이버 자체로만 의미가 있는 것이 아니라 뒤에서 설명할 서비스 매니저에 의해 전체적인 프로세서간 통신이 이루어진다.

Power Management : 안드로이드 시스템은 스마트폰과 같은 모바일 장치를 위한 운영체제다. 따라서 시스템의 사용시간을 늘려주는 전원 관리 방법은 시스템의 매우 중요한 구성 요소다. 안드로이드 시스템에서는 기존의 리눅스 커널이 가지고 있는 전원 관리 방법에 부족한 부분을 추가하여 모바일 장치를 위한 전원 관리 기능을 추가하고 있다. “Wake lock”이라는 관리 방법을 통해 앱 및 시스템에서 필요한 전원 관리 방법을 제어 할 수 있도록 구성하고 있다.




Activity mContext = this;
PowerManager pm = (PowerManager)mContext.getSystemService(
    Context.POWER_SERVICE);
PowerManager.WakeLock    wl    =
pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK
    |PowerManager.ON_AFTER_RELEASE,   
    “MyTag”);
wl.acquire();
 // … Perform operations
wl.release();

[리스트1] Wake Lock을 이용한 전원 관리 방법 프로그래밍의 예

(2) HAL(Hardware Abstraction Layer) 영역
HAL 영역은 안드로이드 시스템에서 하드웨어에 접근하기 위한 인터페이스 제공하는 영역이다. 커널 드라이버와 사용자 드라이버 포함을 하고 있다. 하지만 HAL 영역이라고 명확하게 구분이 되고, 하드웨어에 대한 모든 제어 방법이 포함된 것은 아니다. 안드로이드 버전이 올라갈수록 HAL에 포함되는 하드웨어 지원 및 내용이 점점 늘어가고 있는 추세다. 전화에 관련된 RIL(Radio Interface Layer), GPS, 각종 센서 및 하드웨어 장치들에 대한 제어 방법들이 추가되고 있다. 커널이나 프로세서가 변경이 되어도 하드웨어에 대한 제어 방법을 일정하게 유지할 수 있도록 하기 위한 계층이다. 즉, 이식성을 높이기 위한 계층이라고 보면 되겠다.

(3) 안드로이드 라이브러리
안드로이드 라이브러리는 안드로이드 시스템에서 제공하는 기본적인 화면, 사운드, 멀티미디어 기능들에 대한 기능을 제공하고 있다. C/C++ 라이브러리, Java와 인터페이스를 하기 위해 존재를 하고, Surface Manager의 경우 사용자 인터페이스 Windows 제어를 담당한다. 2D/3D 그래픽 라이브러리를 포함하고 있다.


멀티미디어 코덱, SQLite 데이터 베이스 엔진, Webkit을 바탕으로 하는 웹 엔진을 포함하고 있다.
[그림3]은 안드로이드 라이브러리의 기능 중 화면의 합성 및 관리를 담당하고 있는 Surface Flinger와 사운드의 합성 및 패스의 관리를 담당하고 있는 Audio Flinger의 동작 구조를 보여주고 있다.

SurfaceFlinger - 애플리케이션의 2D/3D Surfaces들을 Framebuffer에서의 구현을 제공  2D/3D Hardware 가속기를 사용하여, blit, rotate, scale, blend 등의 표현이 가능
OpenGL ES Library - Hardware 기반의 OpenGL 가속 기능을 사용할 수 있다.
OpenCORE 기반의 Media Framework - 오디오 및 비디오와 이미지 코덱을 지원  Hardware / Software 코덱과 결합하여 사용, Open MAX IL 인터페이스를 사용
AudioFlinger - 애플리케이션에서 오디오 기능을 제공

(4) 안드로이드 Runtime 영역
JAVA Runtime과 동등한 레벨의 역할을 담당한다.
프로세스가 동작 되면서 라이브러리를 호출 할 때 사용 된다. JAVA 애플리케이션에서 Libc 기반의 C/C++ Library를 호출 할 때 Runtime Library를 호출한다.

Android는 Dex.(Dalvik Executables (DEX)) 실행 파일의 구조를 사용, 실행 파일이 Symbolic Resolution을 통하여 함수를 가지고 있다가 Library를 호출 하는 구조로 되어 있다. 안드로이드 Runtime은 Dalvik VM과 Core Libraries로 구성되어 있다.
Android의 개발은 Eclipse의 ADT Plug-in을 통해서 JAVA로 컴파일 되고, Class와 Resource가 Dx 컨버터를 통해 Android App(.apk)로 변환되어 Dalvik VM위에서 동작하게 된다. Dalvik VM은 작은 메모리에서도 최적화 되는 Dalvik Executable(.dex) 포맷 파일의 실행을 지원하게 된다. Dalvik VM은 스레딩과 저수준의 메모리 관리 지원을 위해 리눅스 커널을 이용하게 된다.


(5) Dalvik VM
비 표준 JAVA Virtual Machine, Android SDK로는 Java 소스를 Dalvik용 bytecode로 직접 컴파일이 불가, DEX File 포맷의 Application을 수행한다.
DX 툴을 사용하여 자바의 .class 파일을 Dalvik용 bytecode로 변환하여 실행 코드를 생성한다. C++ 기반의 Class보다 작고, 호환성이 좋다. SUN(현재는 Orcale)의 라이선스 정책에 따른 라이선스 비용을 회피하기 위하여 개발되었다. JAVA는 GPLv2하의 배포된 오픈소스 였으나 Java ME에서 예외가 발생, 핸드셋에 JAVA를 탑재하기 위해서는 라이선스 비용이 발생한다. Dan Bornstein에 의해 제작되었다.

Java는 Stack-Based Architecture이나 Dalvik VM은 Register-Based Architecture로 모바일 디바이스에 최적화하도록 구성되었고 다수의 VM Instance가 실행 가능 하도록 설계 되었다. Linux Kernel을 사용하여 프로세스의 독립성과 메모리 관리 및 스레딩을 사용할 수 있다는 장점이 존재 한다.

(6) Application Framework 영역
API 기반의 인터페이스를 제공할 수 있도록 구성되었다. Application의 기본적인 소프트웨어 아키텍처를 제공하고 있다. 주로 자바로 구성되었고 Binder 서비스와 매니저들로 되어있다.
Activity Manager - Android 애플리케이션의 수명 주기를 관리
View System - 표준 widget 담당
Window Manager - 모든 응용프로그램과 관련된 화면 담당
Package Manager - 시스템에서 동작중인 응용프로그램들의 정보 담당

안드로이드와 리눅스
일반적인 임베디드 리눅스와 안드로이드 시스템은 [그림5]와 같은 구조적 차이를 보여준다. 즉, 안드로이드는 리눅스 기반 위에 응용 프로그램을 위한 미들웨어 및 프레임웍, JAVA 응용 프로그램을 동작하기 위한 VM(Virtual Machine)을 추가하여 운영하고 있는 구조로 구성되었다.
[그림6]은 안드로이드의 상세적인 내부 구조를 보여준다.




안드로이드의 Root File System


안드로이드 시스템의 Root File System은 기존의 리눅스 Root File System에 System과 Data 디렉터리가 추가되는 형태로 구성되었다. Dalvik VM 본체는 system/bin 디렉터리에 위치하고 프로그램 리소스는 통상 일반 리눅스의 경우 /usr/bin에 위치 하지만 안드로이드의 경우 /system/bin에 위치하는 구조로 구성되었다.

안드로이드의 부팅 과정과 초기화
Android의 부팅 및 초기화 과정은 init라는 프로세서에 의해 이루어 진다. 일반적인 Linux의 일련의 부팅 과정을 전부 하나의 binary인 init에 통합되어 있다.

udev와 관련된 device node 생성 메커니즘도 init에서 처리하도록 구성되었다. 기본적으로 모든 device node는 owner만 Read/Write하게 생성하게 된다. 따라서 이러한 부분을 처리하기 위해서는 초기화를 위해 사용되는 스크립트 파일인 init.rc 혹은 devices.c의 해당 부분을 직접 수정 해야 한다. 안드로이드에서 초기화 과정은 스크립트 파일인 init.rc와 init.%hardware%.rc 를 로딩하여 처리하도록 구성되었다. 통합한 이유는 모바일 운영체제에서 중요한 요소인 보안과 실행 permission의 문제를 통합 관리할 수 있도록 하기 위해서다.

안드로이드에서의 보안과 permission



응용 프로그램과 시스템 사이의 대부분의 보안은 프로세스 수준에서 애플리케이션에 할당된 사용자와 그룹 ID 등 리눅스를 통해서 실행 추가적인 세밀한 보안 기능은 특정 프로세스 수행 할 수 있는 구체적인 작업에 대한 제한을 적용하는 “permission” 메커니즘 등을 통해 제공한다. 따라서 일반 리눅스와의 차이점은 통합된 init 과정을 관리한다는 것이고, 전통적인 /etc/passwd,/etc/group 을 사용하지 않는다는 것이다.
application 권한은 설치할 때, 이러한 permission 이 결정되고, 이 후 변경하지 못하도록 되어 있다. 따라서 모든 안드로이드 애플리케이션은 Android Manifest.xml 파일을 가지고 있으며 이 파일을 통해서 권한 설정하도록 구성되어 있다.

Android Boot 과정


안드로이드 초기화 프로세스는 다음과 같이 동작한다. Init은 Kernel이 시작 된 후 처음으로 시작되는 프로세스다.
(1) Android의 Init은 system/bin/init에 위치, Android의 Init은 다음 단계로 부팅 절차를 수행
(2) Log System 초기화
(3) /init.rc와 /init.%hardware%.rc 의 내용을 파싱
(4) 앞 단계에서 파싱된 사항 중 early-init 부분 수행
(5) 디바이스 노드 생성 및 펌웨어 다운로드
(6) 우선 순위 시스템 및 소유권 초기화
(7) 앞 단계에서 파싱된 사항 중 Init 부분 수행
(8) 우선 순위 시스템 및 소유권 정책 작용
(9) 앞 단계에서 파싱된 사항 중 Early-Boot와 Boot 부분 수행 및 나머지 작업들을 수행

Zygote를 통한 프로세스 관리
Zygote는 애플리케이션을 빠르게 구동하기 위해 미리 fork 되어 있는 프로세스이다. 시스템에서 exec() 호출을 통해 특정 애플리케이션을 실행 하고자 하기 전까지는 중립적인 상태, 즉 특정 애플리케이션과 합체되지 않는 상태를 유지하고 있다. 안드로이드에서 프로세스를 생성하는 방식이다. fork()와 execve()를 통하여 프로세스를 생성하는데, zygote를 통하여 프로세스가 생성되고 메모리를 공유하는 형식을 취한다.
[그림9]와 [그림10]은 안드로이드 구동 과정 중 프로세서의 생성 및 Zygote를 이용한 프로세서 관리의 관계를 보여 주는 그림이다.




안드로이드 시스템 환경에서의 개발
안드로이드 시스템 환경에서 개발 방법은 크게 3가지로 구분할 수 있다. [그림11]과 같이 SDK를 이용하여 일반적인 안드로이드 앱을 개발하는 것이 있을 수 있고, [그림12]와 같이 PDK(Platform Development Kit)를 사용하여 안드로이드 시스템을 특정한 하드웨어에서 사용할 수 있도록 포팅하는 것이다. 본 연재의 대부분의 내용은 PDK를 사용하여 어떻게 안드로이드 시스템을 구성할 것이냐에 초점을 맞추고 있다. 마지막으로 [그림13]과 같이 C/C++을 이용하여 앱을 개발할 때 사용하는 NDK를 이용하는 개발 방법이 있다.


SDK를 통한 개발


PDK를 통한 개발


NDK를 통한 개발



안드로이드의 라이선스
Linux Kernel은 GPL 라이선스를 사용, 따라서 자유로이 배포 가능하나 수정된 내용은 반드시 공개 의무가 있다. Android는 대부분 Apache v2 라이선스를 사용

GPL and Apache
아파치 라이선스는 아파치 웹 서버를 포함한 아파치 재단(ASF: Apache Software Foundation)의 모든 소프트웨어에 적용되며, BSD 라이센스와 비슷하여 소스 코드 공개 등의 의무가 발생하지 않는다. 다만 ‘‘Apache‘‘라는 이름에 대한 상표권을 침해하지 않아야 한다는 조항이 명시적으로 들어가 있고, 특허권에 관한 내용이 포함되어 BSD 라이선스보다는 좀 더 법적으로 완결된 내용을 담고 있다.
특히 Apache License 2.0에서 특허에 관한 조항이 삽입되어 GPL 2.0으로 배포되는 코드와 결합되는 것이 어렵다는 문제가 있었는데, GPL 3.0(안)에서는 이 문제를 해결하여 Apache License로 배포되는 코드가 GPL 3.0으로 배포되는 코드와 결합하는 것이 가능해졌다.




안드로이드와 리눅스
안드로이드 시스템에서 리눅스의 역할은 운영체제의 핵심을 담당하고 있는 커널의 역할을 한다. 따라서 리눅스에 대한 이해는 안드로이드에 대한 동작을 이해하는데 있어 필수적인 요소이다. 리눅스는 오랜 기간 동안 만들어진 운영체제이기 때문에 그만큼 많은 기술 및 복잡한 처리 방법을 가지고 있다. 리눅스와 안드로이드 관계에 대해서 간략히 다루었는데 이 기고를 참고로 하여 안드로이드 시스템의 기본을 이해하는 계기가 될 수 있었으면 한다. 다음 호에는 보다 안드로이드에 대한 핵심적인 내용을 예제 및 소스를 통해 확인해 볼 수 있도록 하겠다.


/필/자/소/개/

필자

라영호

국내 스마트폰의 초창기인 Cellvic에서부터 스마트폰을 개발하였고 윈도 모바일 및 다양한 임베디드 시스템을 개발하고 있다. 현재는 안드로이드 시스템 포팅 및 임베디드 시스템 개발, 컨설팅, 교육 등을 진행하는 회사를 운영하고 있다. 개인 블로그(www.embeddedce.com)를 통해 임베디드 시스템개발에 대한 다양한 생각과 방법론을 함께 생각해 보고자 노력 중이다.

※ 본 내용은 (주)테크월드(http://www.embeddedworld.co.kr)의 저작권 동의에 의해 공유되고 있습니다.
    Copyright ⓒ Techworld, Inc. 무단전재 및 재배포 금지

맨 위로
맨 위로