원글 주소 http://www.bloter.net/archives/206949
애플 ‘메탈 API’, 모바일게임 성능 10배 ↑

한국시각으로 지난 9월11일 진행된 애플의 새 ‘아이폰’ 발표 행사는 이후 수많은 얘깃거리를 낳았다. ‘아이폰6’와 ‘아이폰6플러스’를 중심으로 ‘애플워치’도 이야기의 중심에 섰다. 하지만 만약 게임 업계 관계자라면, 스마트폰에서 더 나은 품질의 게임을 즐기고픈 게이머라면, 그날 애플이 발표한 내용 중에서도 애플의 ‘메탈(Metal)’ 얘기에 귀를 쫑긋 세우지 않았을까. 메탈은 애플이 모바일기기에서 게임 성능을 극대화하기 위해 개발한 새 API다.

한국시각으로 9월18일 애플의 최신 모바일기기용 운영체제 ‘iOS8’이 배포되기 시작했다. 이와 동시에 에픽게임즈에서는 애플의 메탈 API를 적용한 그래픽 미리보기용 게임 ‘에픽 젠 가든’을 배포하기 시작했다. 지금으로서는 게이머가 메탈 API의 진보된 게임 성능을 체험할 유일한 콘텐츠다. 에픽게임즈의 결과물을 바탕으로 애플의 메탈이 앞으로 모바일게임 수준을 어떻게 끌어올릴지 살펴보자.

apple_metal_1_800

모바일게임 성능의 유리천장, ‘오픈GL ES’

애플의 메탈 API가 하는 일을 살펴보려면, 먼저 게임이 하드웨어에서 어떻게 구현되는지 알아야 한다. 게임이 모바일기기 화면에 구현되는 과정은 다음과 같다. 사용자의 입력을 모바일기기가 받으면, 모바일기기 중앙처리장치(CPU)는 그래픽처리장치(GPU)에 그림을 그리라는 명령을 내린다. 이를 ‘드로우콜'(Draw Call)이라고 부른다. CPU의 명령에 따라 GPU가 화면에 뿌려주는, 이를테면 게임 속 텍스처나 사진, 캐릭터 등 모든 요소가 바로 게임 화면을 이루는 핵심이다.

이 과정에서 문제가 생긴다. 수많은 GPU 제조업체가 있고, 각각의 플랫폼에서 한꺼번에 돌아가는 게임을 만드는 것은 불가능하다. 그렇다고 게임 개발자는 어느 한 플랫폼만을 대상으로 게임을 만들 수는 없다. 그래서 나온 것이 바로 ‘오픈GL ES’다. 오픈GL ES는 소프트웨어의 3D 렌더링 기술을 각기 다른 하드웨어에 통합적으로 구현하기 위한 명령어 세트다. 지금까지 오픈GL ES는 아이폰과 안드로이드 스마트폰에서 모바일게임을 구현하기 위한 통합 레이어 역할을 해 왔다.

오픈GL ES의 가장 큰 문제점은 명령어를 전달하고 게임 그래픽을 화면에 구현하는 데까지 걸리는 오버헤드가 많이 발생했다는 점이다. 오버헤드는 명령어가 전달되는 과정 등을 이르는 말이다. 게임 화면을 그리는 하드웨어 처지에서 보면, 게임 구현과 관계가 적은 일종의 ‘추가비용’이 바로 오버헤드다.

예를 들어 CPU가 GPU 쪽에 그림을 그리라는 명령어를 전달하는 과정에서 CPU의 명령어 해석이 필요하다. 이 해석에 도움을 주는 것이 오픈GL ES의 라이브러리인데, 그림을 그리라는 명령어를 해석해 이를 다시 GPU에 전달하는 것 만으로도 CPU에 가해지는 부담이 적잖다. 게임 개발자가 모바일기기에서 게임의 성능을 높이는 것에 가장 큰 걸림돌로 오픈GL ES의 높은 오버헤드를 꼽는 것도 바로 이 때문이다. 오픈GL ES가 범용적인 3D 그래픽을 구현하기 위한 다양한 하드웨어를 목표로 정립된 탓이다.

△ 언리얼엔진으로 제작된 ‘에픽 젠가든’

GPU에 더 가까이

“애플은 명령어를 전달하는 데 오픈GL ES가 아닌 메탈이라는 중간단계 API를 개발한 것입니다. 이전에는 하드웨어 속에서 게임에 필요한 그림을 그리기 위한 명령을 날릴 때 차지하는 비중이 컸는데요. 메탈을 쓰면 이 과정이 짧아집니다.”

애플의 메탈은 오픈GL ES를 대체한다. 신광섭 에픽게임즈코리아 차장은 “모바일기기가 원하는 것은 사용자의 명령에 따라 GPU가 화면에 그림을 그리도록 하는 것뿐인데, 그 과정을 위해 거쳐야하는 해석이나 분석 과정(오버헤드)이 크니 게임의 품질을 높이기 어려웠다”라며 “메탈은 오버헤드를 줄일 수 있도록 돕는다”라고 부연했다.

에픽게임즈가 18일 앱스토어에 출시한 ‘에픽 젠가든’을 보자. 메탈 API가 적용된 콘텐츠로 뛰어난 그래픽 품질을 자랑한다는 점이 특징이다. 그래픽품질 뿐만 아니라 화면에 표현할 수 있는 물체의 수도 획기적으로 늘어났다.

예를 들어 ‘에픽 젠가든’ 화면에 있는 나무 그래픽을 터치하면, 나무에서 수많은 꽃이 핀다. 꽃잎도 동시다발적으로 떨어진다. 꽃과 꽃잎 하나하나가 모두 명령에 의해 처리되는 그래픽 요소다. ‘에픽 젠가든’에서는 나비도 그래픽으로 보여주는데, 사용자의 터치를 따라 움직이는 수많은 나비도 볼 수 있다.

신광섭 차장은 “오픈GL ES를 쓸 때는 CPU가 요소 하나를 그리도록 명령했을 때 발생하는 오버헤드가 커서 한 화면에 많은 오브젝트를 구현하기 어려웠다”라며 “메탈을 쓰면 더 많은 드로우콜을 더 빨리 처리할 수 있어 화면에 표현할 수 있는 요소를 크게 늘릴 수 있다”라고 설명했다.

메탈은 게임의 그래픽품질뿐만 아니라 아이폰의 배터리 사용 시간에도 영향을 미친다. 아이폰이 게임을 구현할 때 CPU에 가해지는 부하를 메탈 API가 근본적으로 줄여주는 덕분이다. 메탈 API를 적용한 게임은 기존 오픈GL ES를 사용하는 게임과 비교해 최대 10배 이상 높은 성능을 낼 수 있다는 게 애플의 주장이다.

apple_metal_4_800

‘에픽 젠가든’에 구현된 나비. ‘메탈’을 쓰면, 손가락을 따라 실시간으로 반응하는 수많은 요소를 동시에 표현할 수 있다.

게임 성능 극대화 바람, 모바일까지

애플의 메탈 API는 마이크로소프트(MS)의 ‘다이렉트X’ 버전 12와 AMD의 새 게임 개발 API ‘멘틀(Mantle)’을 떠올리도록 한다. 다이렉트X는 윈도우 운영체제를 중심으로 다양한 하드웨어를 지원하기 위한 API고, 멘틀은 AMD의 일부 고성능 그래픽카드에 최적화된 게임 개발 API다. 다이렉트X 12와 멘틀 API의 목표는 같다. CPU의 병목현상을 줄이고, GPU가 낼 수 있는 최대의 성능을 활용해 게임 품질을 끌어올리는 것이다.

다시말하면, 메탈 API는 PC 게임 개발 업계의 최근 기술 트렌드를 애플이 재빨리 따라잡은 결과물인 셈이다. 애플의 수직 통합된 하드웨어 정책이 큰 도움이 됐음은 물론이다.

생각해보자. 애플은 하드웨어와 소프트웨어를 모두 만드는 업체다. 아이폰 한 종류에는 칩셋 하나만 탑재된다. 예를 들어 ‘아이폰5S’에는 ‘A7’ 프로세서가, 새로 나온 ‘아이폰6 플러스’에는 ‘A8’ 칩이 들어가 있다. 디자인과 설계 모두를 애플이 담당하는 단일 칩셋으로 게임 개발자는 여기에 최적화된 게임 개발 방법론으로 게임을 코딩하면 된다. 오픈GL ES라는 범용적인 명령어 세트를 더이상 고집하지 않아도 되는 까닭이 여기 있다.

애플의 메탈 API가 적용된 게임으로는 ‘에픽 젠가든’과 앞으로 출시될 ‘베인글로리’ 등이 있다. 애플은 에픽게임즈뿐만이 아니라 일렉트로닉아츠(EA)와 디즈니, 게임로프트, 유비소프트, 징가, 스퀘어에닉스 등 굵직한 게임 개발업체와 손잡았다. 앞으로 아이폰용 모바일게임은 빠른 속도로 품질과 성능을 높여갈 것으로 기대된다. 메탈 API는 A7칩과 A8칩이 탑재된 아이폰에서만 동작한다는 점은 유념하자.

apple_metal_2_800

‘매탈’을 지원하는 게임 개발업체

메탈 API는 수직통합의 산물…구글은?

구글의 안드로이드 OS는 어떨까. PC와 모바일기기 모든 진영에서 하드웨어와 더 밀착하기 위한 게임 개발 방법론이 대세로 떠오른만큼, 구글도 장기적으로는 메탈 API와 비슷한 새 API를 내놓을 가능성이 높다. 하지만 빠른 시간 안에 적용되기는 어렵다. 애플과 전혀 다른 방식으로 운영되는 하드웨어 생태계를 갖고 있기 때문이다.

안드로이드폰은 삼성전자와 LG전자, 중국의 샤오미, ZTE, 화웨이 등이 모두 달려들어 개발 중이다. 각각의 제품 속에는 각기 다른 프로세서가 들어가 있다. 삼성전자가 개발한 제품이라고 해도 퀄컴의 프로세서로 동작하는 스마트폰도 있고, ‘엑시노스’ 칩으로 구동되는 기종도 있다. 다양한 하드웨어를 통합해 지원하기 위한 기술이 오픈GL ES인데, 구글은 이를 대체할 다른 기술을 개발할 수 있을까. 만약 그렇다면, 그것은 애플의 메탈과 같은 형태가 아니라 또 다른 오픈GL ES일 뿐이다.

업계 관계자는 “각각의 그래픽칩셋은 통신을 위한 인터페이스를 적용해야 하는데, 구글이 오픈GL ES외에 다른 것을 만든다고 하더라도 하드웨어 업체가 그 API를 바로 적용할지는 의문”이라며 “여러 하드웨어를 지원하는 안드로이드의 숙명이기도 하다”라고 풀이했다.


'Graphics > 참고' 카테고리의 다른 글

Khronos Vulkan(벌칸) API  (0) 2015.03.27

에딘버러 쉐라톤 호텔(Sheraton Grand Hotel & Spa, Edinburgh)

SPG는 멤버쉽 등록이 되어 있지도 않고 나중에도 갈 예정이 없어,

Topcashbag(www.topcashback.co.uk) 을 경유하여 호텔스닷컴에서 예약 완료


Check In : 2015.03.01

Check Out : 2015.03.02

Room charges : £160.00 (조식 포함)

Room Type : Classic King Room


Airlink를 타고 WestEnd에서 하차 후 도보로 10~15분 정도 소요된다.

호텔 위치는 나쁘지 않은 듯 하고, 조식이 매우 훌륭하다. 사실 쉐라톤을 이용하는 것은 처음이라 더 감동이 있었을수도;;;;;




공항버스에서 내려서 걸어오다보면 보이는 호텔 입구, 다만 Usher Hall 쪽으로 다른 입구도 있지만 사진을 못찍었다.




호텔 로비

웰컴 드링크와 쿠기가 있다.




호텔 객실

방 크기는 작은 편이지만 침대는 킹사이즈로 커서 좋았고 생수 2병이 무료로 제공된다.




'UK& Finland life > Trip' 카테고리의 다른 글

2015.03 에딘버러(Edinburgh) 공항에서 시내 이동  (0) 2015.03.03


올 8월에 여행계획이 있었으나 회사 업무로 인해 1박 2일로 짧게 에딘버러를 다녀왔다.

물론 이번에는 비행기를 타고 갔다왔으나 여름에는 차로 갔다올 생각이다.


에딘버러에서 시내로 가능 방법은 택시, 버스, 트램이 있는듯 한데

공항 출구 바로 앞에 있는 버스(Airlink) 정류장이 있어 버스타고 시내로 이동하기로 결정했다.

버스 티켓은 정류장 앞에서 바로 구매 가능하다.

가격도 매우 저렴(편도 £4, 왕복 £7)하고, 시내까지 20~25분 정도 걸려서 매우 만족스러웠다.


Airlink 티켓 살때 받았는데, Airlink 정류장 및 주변 호텔 정보가 있다.





Airlink는 04:35분 부터 자정까지 10분 간격으로 다니는 듯 하다. 아래 사이트에서 정확한 정보를 얻을 수 있다.


Airlnk 사이트 및 가격 정보('15.03 기준)

http://lothianbuses.com/services/airlink

Ticket typeCost
Single adult£4.00
Single child£2.00
Adult open return£7.00
Child open return£3.00
Adult Airport Day Ticket£9.00
Child Airport Day Ticket£4.50




'UK& Finland life > Trip' 카테고리의 다른 글

2015.03 에딘버러 쉐라톤 호텔  (0) 2015.03.03

웨딩촬영을 위해 회사도 휴가를 냈지만 헤어와 메이크업을 위해 일찍 일어났다.
평소에도 아침을 먹지 않아 오늘도 안먹었지만... 저녁때까지 쭈욱 굶었다는;;;; ㅠ_ㅠ
웨딩 촬영때는 아침을 꼭!!!! 챙겨먹어야 한다.

인터넷에서 신부를 위해 빨대가 달린 음료수와 도너츠를 준비하라고 해서 어제 도너츠는 미리 사놨는데
음료를 준비하지 않아 약간 걱정을 했지만 스튜디오에서 센스 있게 빨대를 준비해줘서 신부가 쉽게 음료수를 먹을 수 있었다.

박스튜디오는 청담동에서 약간 멀리 떨어져있고 찾기 쉽지 않은 단점이 있지만
일반 스튜디오와는 달리 하우스촬영이라는 큰 장점과 여러팀을 동시에 진행하는 것이 아니라
거의 하루에 한팀만 촬영을 해서 여유있게 촬영을 할수 있었다.

박스튜디오의 장점을 얘기하자면 하우스촬영이기에.. 야외에서도 촬영이 가능하다는 것!
그리고 사진을 찍어주시는 작가님도 일반 알바생이 아닌 사장님께서 직접 촬영을 해주셔서 너무 좋았다.
특히! 촬영 시작전에 웃을때 치아가 보이게 웃어야하는지 아니면 그냥 웃어야 하는지 여쭤봤는데
작가님께서는 자연스러운 웃음이 제일 좋다고 하시면서 일부러 치아가 보이게 웃을 필요가 없다고 하시면서
촬영하는 내내 나에게 웃음을 강요하지 않았다.
대부분의 남자들이 작가님들이 웃으라고 강요를 해서 힘들다고 하는데
난 그러한 강요가 없기에 너무 편하고 재미있게 촬영을 할 수 있었다.

자연스러운 표정으로 재미있게 촬영을 하게 해주셔서 작가님~ 다시 한번 감사합니다~

아직 작가님이 찍으신 사진을 보지는 않았지만 같이 간 친구가 찍어준 사진을 보니
조명에 따라 사진이 엄청 다르게 나오는 걸 알게되었다.

촬영날이 날씨가 좋아 정말 다행이었다.
아래 컷은 스튜디오 측면에 나와서 찍은 사진.
이쁜 신부가 추운데 짧은 블랙미니드레스를 입어 고생하긴 했지만 그래도 자연광을 이용해서 찍어 너무 좋았다.
자랑할수 없는 얼굴이기에.. ㅠ_ㅠ

자세히 보면 밖에서 창을 향해 물을 뿌리고 계신다.
원래 조명을 도와주시던 분인데... 이번엔 물을 뿌리시는 역할..
예비 작가님 같으신데 다양한 일을 하신다.
조명 조정 및 물을 뿌리고 의자를 옮기고;;;

그리고 개인적으로 너무 마음에 드는 컷이다.
 삼성결혼도움방에서 알려준 곳들은 모두 인터넷에 정보가 많지 않아
앞으로 결혼 하실분들을 위해 정보를 공유합니다.

박스튜디오를 선택한 이유는
사실 웨딩촬영보다는 본식촬영때문이었는데
아직 본식촬영은 하지 않아 어떨지는 아직 모르겠지만 나중에 본식촬영을 한 후에 업데이트 할 생각입니다.

일단 웨딩촬영에 대해서만 얘기하자면
장점은 야외컷이 포함되어 있고, 사진작가님이 사장님이어서 꼼꼼히 여유있게 촬영이 가능하다는 것.
우리는 1시부터 시작해서 5시 반까지 촬영이 진행됐는데 진행되는 동안 드레스도 여유있게 갈아입고
중간중간에 도너츠를 먹으며 쉬는데도 빨리 하라는 말씀없이 편하게 즐기게끔 분위기를 만들어 준 것이 너무 좋았습니다.

아쉬웠던 부분은
우리가 아무런 준비없이 촬영을 진행하다보니 소품이 많지 않아 소품을 이용한 컷이 별로 없었다는 것입니다.
다른 스튜디오의 앨범을 보다보면 다양한 소품을 이용할 수 있는데
박스튜디오를 선택하실 분은 피켓같은걸 준비하면 도움이 될거 같네요~
사실 다른 스튜디오에서 촬영을 해보지 않아.. 잘 몰라요 ㅎㅎ

2011.05,18 추가 - 사진 수정을 위해 삭제합니다.
 

'Wedding' 카테고리의 다른 글

결혼식 추첨(삼성전자 서초사옥)  (0) 2011.03.03

만난지도 얼마 안됐고 아직 양가 부모님께 인사도 안드렸지만
서초사옥에 가보지도 않구선 서초사옥 결혼식이 좋다는 얘기를 듣고
준비한것 하나 없이 당첨되면 좋고 아니면 말고 라는 마음으로 4월 예식 신청을 했다.

어차피 추첨이고 경쟁률 또한 엄청나서 별 기대를 하지않았지만
신청 당일에 내가 직접갈수 없어서 아버지께 부탁을 드렸는데.. 
3번을 뽑으셨다는.. 연락이 왔다 ㅡ_ㅡv

그렇게 해서 우리 결혼식날이 결정되었다. 양가 부모님 허락없이.... 
단지 추첨으로 인해....ㅋ

예식일 : 2011년 4월 30일 15:00
예식장소 : 삼성전자 서초사옥 5층 다목적실

아래 사진은 
fortunus 님께서 블로그(http://fortunus.tistory.com/5) 에 올린 사진입니다~


식장 모습이다.
12월에 잠깐 서초사옥에 가서 실제 결혼식을 봤는데 회의실이다보니 엄청 넓다.
하객이 많이 안오면 엄청 썰렁해 보일수도 있겠다는 생각이 든다.



신부 대기실
웬지 느낌에 평소에는 VIP 을 위한 장소 같은데
이날은 신부를 위한 장소! 


피로연은 서초사옥 지하 및 사외에 있는데 

사내 : 사와(일식), 소만옥(한식), 리샨(중식), 메드포갈릭(양식)
사외 : 겔라포트(뷔페), 소담(한식)

지하에 있는 곳은 한번에 많은 인원을 소화할수 없을거 같아서
사외에 있는 "겔라포트" 로 결정했다.

원래는 호프집이지만 평일 점심과 예식이 있는 주말은 뷔페를 운영한다고 한다.
실제 예식이 있는 날 가서 계약을 했는데 생각보다 나쁘지는 않았다.

피로연을 선택할때에 먼저 가서 계약하는 사람이 장땡이므로 미리 서두는게 좋다
난 어쩔수 없이 사외를 택했지만 사내에 있는 곳 추천... ㅠ_ㅠ

1. 국민카드 혜택

G마켓, 옥션 5% 할인
알라딘 5% 할인
CGV 6천원 할인, 메가박스/시너스/프리머스 4천원 할인, 인터파크/맥스무비 4천원 할인
커피전문점 10% 할인 또는 적립
백화점 3% 적립
SPC(파리바게트, 파스구찌, 베스킨라빈스, 던킨도너츠 등) 10%할인, 5% 적립
CJ(빕스, 씨푸드오션, 콜드스톤, 차이나팩토리, 더플레이스 등) 20% 할인
투썸 10~15% 할인
뚜레주르 10% 할인
베니건스, 마르쉐, 시즐러, 아웃백 10% 할인
TGI 20% 할인

내가 주로 쓰는 국민카드 혜택은 

1) 이마트 카드

   - 이마트 할인(실적에 따라 차등 적용)
   - 커피전문점 10%할인(3개월 90만 실적 필요)
   - 인터파크 영화예매 4,000원 할인(월2회, 연8회, 무실적, 단 수수료 500원부과)
   - 일반 결제시 0.1% 포인트리적립

차기년도 연회비 해결용, 커피전문전 10% 할인용, 인터파크 영화예매용

영화 예매시 1장을 예매하건 2장을 예매하건 똑같이 4,000원이 할인되므로
동시에 2장을 결제하지 말고 1장씩 2번 나눠서 결제하도록 하자.
주말의 경우 장당 5500원에 볼 수 있다.
(1장 = 9.000-4.000+500=5,500)

2) CJ 카드

   - CJ계열사 10~20% 할인, CJ 포인트 1~2%적립
   - 뚜레주르 10%할인(통신사 카드와 중복 불가)
   - CJ홈쇼핑 3% 적립, CJ몰 2% 적립
   - CGV 8,500원 이상 결제시 6천원할인, 미만 결제시 3천원할인(일1회, 연12회, 3개월 90만 실적 필요)
   - 포인트리 미적립

할인횟수가 일 1회로 제한되므로 2장을 예매하고 싶을 때에는
자정을 기다렸다가 11시 55분에 한 번, 0시 5분에 한 번 이렇게 두 번 결제 하면 된다.

3) &D 카드 - 현재 발급중지
   - 팸레 20% 적립(월 20만원 이용분까지)
   - 커피 전문점 20% 적립(월 10만원 이용분까지)
   - Yes24 / 티켓링크 10% 적립(각 가맹점 별 월 10만원 이용분까지)
   - 총 적립한도는 본인 기준 연간 30만점
   - 에버랜드 50%, 캐리비언 30%
   - 맥스무비 영화 1매당 3500원 할인(최고 7천원, 단 직전 3개월 월 평균 30만원 이상시)
   - 포인트리 0.5% 적립(교통카드 이용포함)

Yes24는 CJ 몰 경유하면 CJ몰 적립급도 3%

4) 마이원카드 - 아직 미발급

   - CGV, 메가박스, 프리머스, 시너스 4천원 할인(월2회, 연8회, 3개월 30만 실적 필요)
   - 스타벅스 10% 할인(3개월 30만 실적 필요)
   - 아웃백, TGI, 마르쉐, 베니건스, 시슬러 10% 할인(중복할인 가능, 무실적, 일1회, 일20만 한도)
   - 포인트리 0.1%적립

CGV 외 영화관 4천원 할인용

5) 해피포인트 체크카드(반굴비카드) - 아직 미발급

   - 해피포인트 가맹점에서 5천원 이상 결제시 10% 할인, 5% 적립(단, 1개월 10만 실적 필요)
   - 해피포인트 가맹점에서 1천원 이상 결제시 5%적립
   - G마켓, 옥션 3만원 이상 결제시 5% 할인(단, 1개월 10만 실적 필요)
   - CGV, 메가박스, 프리머스 7천원 이상 결제시 3천원 할인(월 2회, 연12회, 1개월 10만 실적 필요)
   - 카드사용내역 문자 전송 무료
   - 포인트리 미적립

해피포인트 할인 및 적립용, , G마켓 및 옥션 할인용, 영화 할인용, sms신청용

국민 신용카드를 신청해서 사용하더라도 sms는 서비스되지 않는다.
하지만 국민 체크카드를 사용한다면 사용 여부를 문자로 알려주는 sms 서비스가 공짜다.
고로 체크카드 사용은 필수다.

반굴비카드이므로 실적을 위해 10만원은 무조건 체크카드부터 이용하자.
단, 포인트리가 미적립이므로 10만원만 딱 쓰고 말자.
(사용 내역을 알려주는 문자를 따로 보관해서 10만원 채워지는 동시에 신용카드를 사용하도록 할 것)
나머지는 0.3% 적립되는 포인트파크 카드 이용하자


커피, 팸래는 &D를 이용해서 월 10만원까지 20% 할인받고
나머지 가맹점은 이용을 잘 안해서 아직까지는 다른 카드의 필요성을 못느끼겠다.


이 글은 일체유시조님의 블로그에서 참고했습니다.
http://blog.naver.com/ashzero/150082797229


















'Finance > MyCards' 카테고리의 다른 글

신한 레이디클래식  (0) 2021.04.24
롯데 카카오  (0) 2021.04.24
롯데 인터파크  (0) 2021.04.24
롯데 벡스2  (0) 2021.04.24
MileStory (마일스토리 카드)  (0) 2010.08.11

 
 
 
 

항목

혜택

조건

주유 할인 및
포인트 적립
주유할인
(리터당 60원)
포인트 적립
(리터당 5포인트)

-주유할인 : 월 4회 / 1회 최대 10만원
-포인트적립 : 이용 시 마다 적립 (LPG제외)
-적립된 GS&POINT를 사용하시려면 GS&POINT 회원등록을 하셔야 합니다. (www.gsnpoint.com)
휘발유, 등유, 경유는 GS주유 고시 휘발유가 기준으로 환산할인


(전항목 공임가
포함 할인 혜택)

엔진오일 교환

무료

-연 1회.  4L 기준 (G1, D1, 오일필터 포함)
-4L초과 시 고객부담금 발생
-초년도 : 신용카드 1회 이상 사용 시 교환
-차년도 : 연간 이용실적 240만원 이상 사용 시 교환
-수입차, 1톤 초과 화물 트럭은 제외
오일필터 및 엔진오일 종류/용량 등에 따라 추가요금이
발생할 수 있습니다.

차량경정비

최대 50% 할인

-

부동액 교환

30% 할인

연 1회.  GS CX 부동액에 한함 (전용 부동액 제외)

브레이크 오일(DOT-3)

30% 할인

연 1회.  DOT-4 한함

브레이크 패드 교환

20% 할인

연 1회.  상신 일반 패드 및 하드론 패드 한함.

오토밋션오일 교환

30% 할인

연 1회.  10L,GS 오토밋션 오일에 한함. (전용 오일 제외)

항균필터 교환

30% 할인

연 1회.  LG 화학 캐비너 항균 필터에 한함.

에어컨가스 완충

40% 할인

연 1회

와이퍼 교환

50% 할인

연 1회.  캐프 와이퍼 기준 (체어맨, 베라크루즈등의 전용 와이퍼 차량 제외)

타이어 위치 교환

무료

연 1회 (휠 밸런스는 앞 타이어 2개에 한함.)

타이어 펑크 수리

무료

횟수 제한 없음

부가서비스

전규류 무상 교환,
무상점검(21가지)

전조등, 안개등, LED제외

(중고차 구매시
최초 1회, GS카넷 직영점에
한함)

엔진오일 교환

무상교환

-최초 1년간 3회 (중고차 구매시)
-KIXX G1, D1에 한함
-수입차, 1톤 초과 화물 트럭은 제외
-카넷본사에서 오프라인 무료 엔진오일교환권 3매를 우편발송으로 제공하며, 유효기간은 구매일로 부터 1년간 사용가능함
- 가맹점을 제외한 전국 autoOasis 전국 직영점에서 사용할 수 있음

차량 A/S 보증

무상보증

-최초 1년간 1만2천 Km 보장 (중고차 구매시)
-신차 출고 이후 8년 , 15만km 내 차량에 한함


상품 할인쿠폰 제공

20% 할인쿠폰

 

에서 특정 상품별
쿠폰 출력 후 사용

 


항목

혜택

조건


숙박예약

호텔예약할인

2~4% 할인  

회원으로 로그인 후 이용

펜션예약할인

2~4% 할인  
스파예약할인 2~4% 할인  


렌터카


렌터카 할인
렌터카 30 ~ 40% 할인   회원으로 로그인 후 이용
(제주지역은 최저가상품으로 추가할인이 없습니다.)
금호렌터카 30% 현장할인

예약문의 : 02-1588-1230
(제주지역 제외)


여행

테마해외여행
할인

투어마일스토리 해외레저체험여행 5% 할인
해외여행상품 5~9% 할인 (모두투어, 하나투어 등 주요여행사 상품 할인)

 

항공권 할인

국내선 5%, 국제선 7% 할인

문의 : 코리아하트클럽,
02-540-7780

놀이공원

전국 놀이공원 10곳 할인
- 케리비안베이 : 본인입장료 30% 현장할인
- 에버랜드(용인), 롯데월드(서울) : 자유이용권 본인 50% 현장할인
- 서울랜드(과천), 우방랜드(대구), 꿈돌이랜드(대전), 통도환타지아(부산) :
본인무료입장 또는 자유이용권 본인 50% 현장할인
- 경주월드(경주) : 본인 무료입장 또는 자유이용권 본인 50% 현장할인 또는 캘리포니아 비치 30% 현장할인 중 (택일)
- 패밀리랜드(광주) : 본인무료입장, 결제 후 1인 해당금액 차감청구
- 전주시 동물원(전주) : 본인무료입장, 현장할인

(통합 월 1회, 연 4회)


쇼핑


쇼핑 할인

Shopping Mall에서 멤버십 회원용 특가 할인 Corner 운영

진행예정
무이자할부

4대 백화점, 3대 할인점 업종 2~3개월 무이자 할부

4대 백화점 : 롯데,신세계,현대,갤러리아
3대 할인점 : 이마트,홈플러스,롯데마트

면세점 할인

면세점 5~15% 할인쿠폰

사용방법 : 비씨카드 홈페이지 → 서비스 신청 및 변경 → 부가서비스 → 면세점 할인쿠폰 출력 후 사용


헬스

건강검진

KMI(한국의학연구소) 종합검진 할인

예약 및 상담 : 1599-7070, www.kmi.or.kr

 

항목

혜택

조건

캐시백

1만원이상 이용시 1천원 캐쉬백

1일 1회, 월 10회
주유, 통신, 외식, 영화, 놀이공원, 무이자할부(백화점 및 할인점) 서비스 제공 가맹점 이용 시 1천원 서비스 미제공

통신요금할인

휴대폰 이용대금 자동이체 시 3%할인

월 1회, 최초 승인건, 통신료 최대 1,200원 할인

외식

, 10% 캐시백

통합 월 1회, 1만원 한도

금융

기업은행 CD/ATM 인출수수료 월 10회 면제

 

영화

, 2천원 현장할인

통합 월 1회, 연 6회

부동산 중개수수료할인

부동산 법정 중개수수료 10% 할인
- 제휴처를 통한 부동산 법정 중개수수료 결제시 할인(이용대금 차감청구)

제휴처 : ㈜부동산플래너
(문의 : 1566-5353 / www.vuple.co.kr)

* 매장에서도 마일스토리 멤버십 신용카드를 신청하실 수 있습니다.

'Finance > MyCards' 카테고리의 다른 글

신한 레이디클래식  (0) 2021.04.24
롯데 카카오  (0) 2021.04.24
롯데 인터파크  (0) 2021.04.24
롯데 벡스2  (0) 2021.04.24
국민카드 정리  (0) 2010.08.24

Android 부팅중 init 프로세스의 동작에 대한 설명이다.

========================================================================================================

출처 : http://blog.daum.net/baramjin/16010995

안드로이드의 초기화 과정 중 Init 프로세스를 생성하고 init 프로세스가 동작하는 과정에 대하여 정리한다.

 

Init 프로세스는 부팅 과정에서 커널이 생성하는 첫번째 프로세스로 PID는 1이다.

리눅스 커널의 부팅 과정을 보면 알겠지만 다음 과정에서 생성된다.

 

/kernel/init/main.c 파일을 참조하면 다음과 같은 초기화 과정을 거친다.

 

start_kernel()

rest_init()

kernel_init()

init_post()

 

init_post()에서 init 프로세스를 생성하는데, 이를 위해서 ramdisk_execute_command를 kernel_init()에서 "/init" 으로 설정하고 access 여부를 확인한다. run_init_process()에서는 입력된 파일명을 실행하는 역활만을 한다.

 

static int noinline init_post(void)
{
        free_initmem();
        unlock_kernel();
        mark_rodata_ro();
        system_state = SYSTEM_RUNNING;
        numa_default_policy();

 

        if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
                printk(KERN_WARNING "Warning: unable to open an initial console.\n");

        (void) sys_dup(0);
        (void) sys_dup(0);

 

        current->signal->flags |= SIGNAL_UNKILLABLE;

 

        if (ramdisk_execute_command) {
                run_init_process(ramdisk_execute_command);
                printk(KERN_WARNING "Failed to execute %s\n",
                                ramdisk_execute_command);
        }

 

        /*
         * We try each of these until one succeeds.
         *
         * The Bourne shell can be used instead of init if we are
         * trying to recover a really broken machine.
         */
        if (execute_command) {
                run_init_process(execute_command);
                printk(KERN_WARNING "Failed to execute %s.  Attempting "
                                        "defaults...\n", execute_command);
        }
        run_init_process("/sbin/init");
        run_init_process("/etc/init");
        run_init_process("/bin/init");
        run_init_process("/bin/sh");

 

        panic("No init found.  Try passing init= option to kernel.");
}

 

이후에 /sbin/init, /etc/init, /bin/init, /bin/sh 를 실행하는 코드가 있는데 안드로이드의 경우 실제 이와 관련된 파일이 없기 때문에 위의 과정으로만 처리가 된다.

 

안드로이드에서 init 프로세스와 관련된 코드는 /system/core/init/init.c 에 있다. init 프로세스가 하는 중요한 작업 중 하나는 init.rc 파일을 처리하는 것이다.

안드로이드에서 기본적으로 사용하는 init.rc 파일은 /system/core/rootdir/init.rc 파일이다. /system/core/rootdir/Android.mk 파일을 보면 init.rc 파일을 target 디렉토리로 복사하도록 하고 있다.

 

init 프로세스의 기본 기능을 다시 한번 정리하면 다음과 같다.

1) SIGCHLD signal 처리

2) rc 파일 처리 (init.rc 와 init.xxx.rc)

3) 디바이스 초기화와 관리

4) 기본 property 설정

 

 이중 rc 파일 처리를 보면 다음과 같다.

 

    INFO("reading config file\n");
    parse_config_file("/init.rc");

 

    /* pull the kernel commandline and ramdisk properties file in */
    qemu_init();
    import!_kernel_cmdline(0);

 

    get_hardware_name();     
    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
    parse_config_file(tmp);

 

처음 init.rc 파일을 분석해서 서비스(Service) 리스트와 액션(Action) 리스트를 만든다.

 

다음으로 import!_kernel_cmdline()을 호출해서 필요한 내용을 전역 변수에 저장한다. 이를 보면 /proc/cmdline을 읽어와서 이를 분석하여 저장하는데 /proc/cmdline에 저장된 내용은 kernel 컴파일시 CONFIG_CMDLINE에 정의한 문자열 (/kernel/.config 파일 참조)이다.

 

static void import!_kernel_cmdline(int in_qemu)
{
    char cmdline[1024];
    char *ptr;
    int fd;

 

    fd = open("/proc/cmdline", O_RDONLY);
    if (fd >= 0) {
        int n = read(fd, cmdline, 1023);
        if (n < 0) n = 0;

        /* get rid of trailing newline, it happens */
        if (n > 0 && cmdline[n-1] == '\n') n--;

        cmdline[n] = 0;
        close(fd);
    } else {
        cmdline[0] = 0;
    }

 

    ptr = cmdline;
    while (ptr && *ptr) {
        char *x = strchr(ptr, ' ');
        if (x != 0) *x++ = 0;
        import!_kernel_nv(ptr, in_qemu);
        ptr = x;
    }

        /* don't expose the raw commandline to nonpriv processes */
    chmod("/proc/cmdline", 0440);
}

 

arm의 경우는 CONFIG_CMDLINE으로 정의된 문자열을 /kernel/arch/arm/kernel/setup.c 에서 처리한다.

하여간에 import!_kernel_cmdline()을 보면 /proc/cmdline의 내용을 읽어와서 import!_kernel_nv()를 이용해서 전역 변수(console, bootmode, serialno, baseband, carrier, bootloader, hardware)에 저장한다.

 

내 안드로이드 환경에서는 CONFIG_CMDLINE의 문자열은 다음과 같다. androidboot.hardware만 정의하기 때문에 전역 변수 hardware 값만 설정된다.

 

CONFIG_CMDLINE="root=/dev/ram rw initrd=0x40600000,0x400000 init=/init console=ttySAC0 mem=200M androidboot.hardware=tcc92xx"

 

마지막으로 get_hardware_name()을 호출해서 hardware 이름(xxx라고 가정)을 얻어낸 후, init.xxx.rc 파일을 분석해서 역시 서비스 리스트와 액션 리스트를 만든다. init.rc가 안드로이드에서 기본적으로 수행해야할 서비스들을 정리한다고 하면 init.xxx.rc에는 하드웨어 의존적인 초기화 과정을 만들어 두어야 한다.

 

get_hardware_name()을 보면 /proc/cpuinfo의 내용을 읽어서 전역 변수 hardware와 revision을 다시 설정하는데 왜 다시 처리하는지는 모르겠다.

 

일단 init,rc와 init.xxx.rc (내 보드에서는 init.tcc92xx.rc)을 분석해서 서비스 리스트와 액션 리스트를 만드는 것은 parse_config_file()이 한다. 이 함수는 /system/core/init/parser.c 에 있다.

 

init.rc 파일은 on init 에서 수행해야 하는 액션 리스트와 on boot에서 수행해야 하는 액션 리스트가 있다.

 

on init

sysclktz 0

loglevel 3

# setup the global environment
    export PATH /sbin:/system/sbin:/system/bin:/system/xbin
    export LD_LIBRARY_PATH /system/lib
    export ANDROID_BOOTLOGO 1
    export ANDROID_ROOT /system
    export ANDROID_ASSETS /system/app
    export ANDROID_DATA /data
    export EXTERNAL_STORAGE /sdcard

# Backward compatibility
    symlink /system/etc /etc

# create mountpoints and mount tmpfs on sqlite_stmt_journals
    mkdir /sdcard 0000 system system
    mkdir /system
    mkdir /data 0771 system system
    mkdir /cache 0770 system cache
    mkdir /sqlite_stmt_journals 01777 root root
    mount tmpfs tmpfs /sqlite_stmt_journals size=4m

    mount rootfs rootfs / ro remount

    write /proc/sys/kernel/panic_on_oops 1
    write /proc/sys/kernel/hung_task_timeout_secs 0
    write /proc/cpu/alignment 4
    write /proc/sys/kernel/sched_latency_ns 10000000
    write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000
    write /proc/sys/kernel/sched_compat_yield 1

# Create cgroup mount points for process groups
    mkdir /dev/cpuctl
    mount cgroup none /dev/cpuctl cpu
    chown system system /dev/cpuctl
    chown system system /dev/cpuctl/tasks
    chmod 0777 /dev/cpuctl/tasks 

......

 

# mount mtd partitions

    # Mount /system rw first to give the filesystem a chance to save a checkpoint
    mount yaffs2 mtd@system /system
    mount yaffs2 mtd@system /system ro remount

 

...... 


# create basic filesystem structure
    mkdir /data/misc 01771 system misc
    mkdir /data/misc/hcid 0770 bluetooth bluetooth
    mkdir /data/misc/keystore 0770 keystore keystore

  

on boot
# basic network init
    ifup lo
    hostname localhost
    domainname localdomain

# set RLIMIT_NICE to allow priorities from 19 to -20
    setrlimit 13 40 40

# Define the oom_adj values for the classes of processes that can be
# killed by the kernel.  These are used in ActivityManagerService.
    setprop ro.FOREGROUND_APP_ADJ 0
    setprop ro.VISIBLE_APP_ADJ 1
    setprop ro.SECONDARY_SERVER_ADJ 2
    setprop ro.BACKUP_APP_ADJ 2
    setprop ro.HOME_APP_ADJ 4
    setprop ro.HIDDEN_APP_MIN_ADJ 7
    setprop ro.CONTENT_PROVIDER_ADJ 14
    setprop ro.EMPTY_APP_ADJ 15

# Define the memory thresholds at which the above process classes will
# be killed.  These numbers are in pages (4k).
    setprop ro.FOREGROUND_APP_MEM 1536
    setprop ro.VISIBLE_APP_MEM 2048
    setprop ro.SECONDARY_SERVER_MEM 4096
    setprop ro.BACKUP_APP_MEM 4096
    setprop ro.HOME_APP_MEM 4096
    setprop ro.HIDDEN_APP_MEM 5120
    setprop ro.CONTENT_PROVIDER_MEM 5632
    setprop ro.EMPTY_APP_MEM 6144

# Write value must be consistent with the above properties.
# Note that the driver only supports 6 slots, so we have HOME_APP at the
# same memory level as services.
    write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15

    write /proc/sys/vm/overcommit_memory 1
    write /proc/sys/vm/min_free_order_shift 4
    write /sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144

    # Set init its forked children's oom_adj.
    write /proc/1/oom_adj -16

    # Permissions for System Server and daemons.
    chown radio system /sys/android_power/state
    chown radio system /sys/android_power/request_state
    chown radio system /sys/android_power/acquire_full_wake_lock
    chown radio system /sys/android_power/acquire_partial_wake_lock
    chown radio system /sys/android_power/release_wake_lock
    chown radio system /sys/power/state
......


# Define TCP buffer sizes for various networks
#   ReadMin, ReadInitial, ReadMax, WriteMin, WriteInitial, WriteMax,
    setprop net.tcp.buffersize.default 4096,87380,110208,4096,16384,110208
    setprop net.tcp.buffersize.wifi    4095,87380,110208,4096,16384,110208
    setprop net.tcp.buffersize.umts    4094,87380,110208,4096,16384,110208
    setprop net.tcp.buffersize.edge    4093,26280,35040,4096,16384,35040
    setprop net.tcp.buffersize.gprs    4092,8760,11680,4096,8760,11680

 

분석되어 리스트로 만들어진 액션들은 다음 코드들에 의하여 실행된다. (/system/core/init/main.c)

 

int main(int argc, char **argv)

    action_for_each_trigger("early-init", action_add_queue_tail);
    drain_action_queue();

 

......

 

         /* execute all the boot actions to get us started */
    action_for_each_trigger("init", action_add_queue_tail);
    drain_action_queue();

 

...... 

 

    /* execute all the boot actions to get us started */
    action_for_each_trigger("early-boot", action_add_queue_tail);
    action_for_each_trigger("boot", action_add_queue_tail);
    drain_action_queue(); 

 

코드를 보면 early-init, init, early-boot, boot 에 따른 액션 리스트를 실행하는데, 안드로이드에서 사용하는 init.rc에 early-init과 early-boot가 없기 때문에 init과 boot에 해당하는 액션만 실행된다.

init은 주로 전역 변수 초기화, 마운트 포인트(mount point) 생성, MTD 파티션 마운트, 기본적인 파일 시스템 구조를 생성하며,

boot는 네트웍을 초기화 하며, 접근 권한 등을 설정하고, APP group의 메모리 사용량을 설정한다.

 

서비스의 경우는 class_start default 로부터 정의된다.

 

    class_start default

## Daemon processes to be run by init.
##
service console /system/bin/sh
    console

# adbd is controlled by the persist.service.adb.enable system property
service adbd /sbin/adbd
    disabled

# adbd on at boot in emulator
on property:ro.kernel.qemu=1
    start adbd

 

...... 

 

service servicemanager /system/bin/servicemanager
    user system
    critical
    onrestart restart zygote
    onrestart restart media 

 

 서비스들을 정의하는 방법은 다음과 같다.

 

service <name> <pathname> [<argument>]

<option>

..... 

<option> 

 

 즉 위의 예를 보면 servicemanager는 /system/bin/servicemanager를 실행해야 하며 user system, critical과 onstart 옵션을 가진다는 것을 알 수 있다. critical은 안드로이드의 운영 정책으로 4번 오류 발생시 reboot한다는 의미라고 한다. onrestart는 해당 서비스가 재시작되면 다음의 서비스를 다시 시작하라는 말이다. 즉 servicemanager가 재시작되면 zygote와 media도 다시 시작해야 한다.

(/system/core/init/readme.txt 참조)

 

서비스 리스트들은 어떻게 시작될까?

이 부분에 대해서는 다음 포스팅을 일단 참조한다. (http://andstudy.springnote.com/pages/3872497)

 

일단 init 프로세스가 동작하면 루프를 돌면서 restart_process(0를 호출하는데 여기에서 처리되는 것 같다. 좀 더 정리하면 좋겠지만 다른 일로 나중에 정리한다.

 

    for(;;) {
        int nr, i, timeout = -1;

        for (i = 0; i < fd_count; i++)
            ufds[i].revents = 0;

        drain_action_queue();
        restart_processes();

        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

#if BOOTCHART
        if (bootchart_count > 0) {
            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                timeout = BOOTCHART_POLLING_MS;
            if (bootchart_step() < 0 || --bootchart_count == 0) {
                bootchart_finish();
                bootchart_count = 0;
            }
        }
#endif
        nr = poll(ufds, fd_count, timeout);
        if (nr <= 0)
            continue;

        if (ufds[2].revents == POLLIN) {
            /* we got a SIGCHLD - reap and restart as needed */
            read(signal_recv_fd, tmp, sizeof(tmp));
            while (!wait_for_one_process(0))
                ;
            continue;
        }

        if (ufds[0].revents == POLLIN)
            handle_device_fd(device_fd);

        if (ufds[1].revents == POLLIN)
            handle_property_set_fd(property_set_fd);
        if (ufds[3].revents == POLLIN)
            handle_keychord(keychord_fd);
    }

 

 init.rc에 의해서 수행되는 서비스는 다음과 같다.

console, abdb, servicemanager, vold, nexus(?), debuggerd, ril-daemon, zygote, media, bootsound, bootanim, dbus, hcid, hfag, hsag, installd, flash_recovery, racoon, httpd, keystore

 


http://blog.daum.net/baramjin/16010995


'Platform > Android' 카테고리의 다른 글

[Android] Android 부팅  (0) 2010.03.18
[Android] Android 의 개요  (0) 2010.03.18
[Android] Boot Animation  (0) 2010.03.18
[Android] SGL  (0) 2010.03.18
[Android] Surface Flinger의 쓰레드  (1) 2010.03.18

안드로이드의 부팅 순서

========================================================================================================

출처 : http://blog.daum.net/baramjin/16010975

안드로이드는 리눅스 커널을 이용한다. 따라서 리눅스의 시작 시퀀스 이후에 안드로이드 고유 시스템이 동작하게 된다.

기본적인 동작을 잘 설명한 곳( http://samse.tistory.com/112?srchid=BR1http%3A%2F%2Fsamse.tistory.com%2F112 )이 있어서 일부 발췌해 온다.

 

 


리눅스는 기본적으로 init이 가장먼저 실행된다. init.rc 라는 이름의 파일에는 init이 해야할 작업들이 기록되어 있다. 파일시스템 마운팅, 폴더 권한설정, 캐시폴더 삭제, 시작프로그램 동작 등이 기록되어 있다. 우선 데몬을 올린다. 데몬은 init에 의해 리눅스와 같이 시작되었다가 리눅스가 종료될 때 없어지는 프로그램으로서 데몬을 작성하는 규격에 따라 만들어져야 한다. Zygote가 Dalvik을 초기화 한다. C 밑에 있는 기본라이브러리들은 런타임을 통해 실행되고 상위 서비스들은 Dalvik을 통해 실행된다. 이러한 과정들을 위한 설정은 해당하는 config 파일을 수정하면 된다. 어떤 동작들을 바꾸고 싶으면 기본적으로 init.rc를 바꾸면 되고 Zygote를 바꾸고 싶으면 그 설정파일을 바꾸면 된다. 그리고 시스템서버, 서페이스매니저, 오디오매니저들이 올라간다. 그 다음에는 시스템 서비스들이 활성화 된다. 이들은 서비스이므로 서비스매니저에 등록된다. 

 

init은 /system/core/init 디렉토리에 관련 소스가 있다. init.rc 파일은 /system/core/rootdir/에 있다.

init이 하는 일과 init.rc 파일을 작성하는 방법에 대해서는 여기( http://www.aesop.or.kr/?document_srl=46566 )를 참조한다.

  

init이 하는 일을 정리하면 다음과 같다.

1. log system 초기화

2. /init.rc와 /init.%hardware$.rc 파일 파싱

3. 2번 스텝의 2개 파일에서 초기 선동작(early-init action) 수행

4. 디바이스 종속적인 초기화 작업 (예를 들어 /dev 에 모든 디바이스 노드 만듬)

5. property system 초기화 (property system은 공유 메모리로 동작하며 윈도우의 레지스트리와 같은 역활이다)

6. 2번 스텝의 2개 파일에서 초기 동작(init action) 수행

7. property service 시작

8. 2번 스텝의 2개 파일에서 선부팅(early boot), 부팅(boot) 동작 수행

9. 2번 스텝의 2개 파일에서 property 동작 수행

10.  device/property가 /child process를 셋할때까지 대기하면서 rc 파일에 정의된 명령어를 수행한다.

 

 

위의 설명처럼 /out/target/product/XXX/init.rc 를 먼저 살펴 보자.  위에서 설명한 것처럼 폴더 권한 설정 등의 초기화 작업을 하고 나면

Demon을 올리는 작업을 하도록 되어 있다. 이를 정리하면 다음과 같다.

 

1) console : shell 을 시작 (system/core/sh/)

## Daemon processes to be run by init.
##
service console /system/bin/sh
    console

 

2) abdb : abdb daemon을 시작 (system/core/adb/)

# adbd on at boot in emulator
on property:ro.kernel.qemu=1
    start adbd

 

on property:persist.service.adb.enable=1
    start adbd

 

on property:persist.service.adb.enable=0
    stop adbd

 

3) servicemanager : binder system을 시작 (framework/base/cmds/servicemanager/)

service servicemanager /system/bin/servicemanager
    user system
    critical
    onrestart restart zygote
    onrestart restart media

 

4) vold : volume daemon 시작 (system/core/vold/)

service vold /system/bin/vold
    socket vold stream 0660 root mount

 

#service mountd /system/bin/mountd
#    socket mountd stream 0660 root mount

 

5) debuggerd : debug system을 시작 (system/debuggerd/)

service debuggerd /system/bin/debuggerd

 

6) rild : radio interface layer daemon을 시작 (hardware/ril/rild/)

service ril-daemon /system/bin/rild
    socket rild stream 660 root radio
    socket rild-debug stream 660 radio system
    user root
    group radio cache inet misc

 

7) Zygote : (frameworks/base/cmds/app_process/)

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on

 

8) media : AudioFlinger, MediaPlayerService, CameraService를 시작 (frameworks/base/media/mediaserver/)

service media /system/bin/mediaserver
    user media
    group system audio camera graphics inet net_bt net_bt_admin

 

관련 코드를 보면 굉장히 간단하다. (framework/base/media/mediaserver/main_mediaserver.cpp)

int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p", sm.get());
    AudioFlinger::instantiate();
    MediaPlayerService::instantiate();
    CameraService::instantiate();

    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

 

9) bootsound : boot sound (system/media/audio/ui/boot.mp3)를 재생, (그런데 이 바이너리는 실제 찾을 수 없네...?. 그리고 샘플 파일도 안 만들어 지네)

service bootsound /system/bin/playmp3
    user media
    group audio
    oneshot

 

10) dbus : dbus daemon 시작 (BlueZ 즉 Bluetooth 관련 서비스) (external/dbus/bus/)

service dbus /system/bin/dbus-daemon --system --nofork
    socket dbus stream 660 bluetooth bluetooth
    user bluetooth
    group bluetooth net_bt_admin

 

11) hcid : hcid의 stdout, stdin을 안드로이드 logging sytstem으로 redirect (external/bluez/hcid/)

service hcid /system/bin/hcid -s -n -f /etc/bluez/hcid.conf
    socket bluetooth stream 660 bluetooth bluetooth
    socket dbus_bluetooth stream 660 bluetooth bluetooth
    # init.rc does not yet support applying capabilities, so run as root and
    # let hcid drop uid to bluetooth with the right linux capabilities
    group bluetooth net_bt_admin misc
    disabled

 

12) hfag : Bluetooth handsfree audio gateway 시작 (BlueZ 만 사용) (external/bluez/utils/tools/)

service hfag /system/bin/sdptool add --channel=10 HFAG
    user bluetooth
    group bluetooth net_bt_admin
    disabled
    oneshot

 

13) hsag : Bluetooth headset audio gateway 시작 (BlueZ 만 사용) (external/bluez/utils/tools/)

service hsag /system/bin/sdptool add --channel=11 HSAG
    user bluetooth
    group bluetooth net_bt_admin
    disabled
    oneshot

 

14) install : install package daemon 시작 (frameworks/cmds/installd/)

service installd /system/bin/installd
    socket installd stream 600 system system

 

15) flash_recovery : /system/recovery.img를 로드 (bootable/recovery/mtdutils/)

service flash_recovery /system/bin/flash_image recovery /system/recovery.img
    oneshot 

 

  

강조한 것처럼 바와 같이 servicemanager을 이용해서 zygote와 media를 시작하고 SD 카드와 USB의 mount 등을 처리하는 vold 데몬을 올린다. 이후 부팅 사운드를 재생하거나 다른 필요한 데몬들을 올리게 된다. 이후 다시 강조한 부분을 보면 zygote를 이용해서 system server 를 시작한다. 이후 media를 다시 시작한다(?)

 

안드로이드의 system server는 Native Service와 여러가지 기본 서비스(core system service 라고도 한다)들로 이루어진다.

 

/framework/base/cmds/system_server/library/system_init.cpp 를 보면 system_init() 함수가 있다. 이 파일은 실제 사용한다기 보다는 초기화 흐름을 알게 해주는 코드로 보인다.

 

extern "C" status_t system_init()
{
    LOGI("Entered system_init()");
    
    sp<ProcessState> proc(ProcessState::self());
    
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p\n", sm.get());
    
    sp<GrimReaper> grim = new GrimReaper();
    sm->asBinder()->linkToDeath(grim, grim.get(), 0);
    
    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsurfaceflinger", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the SurfaceFlinger
        SurfaceFlinger::instantiate();
    }

    // On the simulator, audioflinger et al don't get started the
    // same way as on the device, and we need to start them here
    if (!proc->supportsProcesses()) {

        // Start the AudioFlinger
        AudioFlinger::instantiate();

        // Start the media playback service
        MediaPlayerService::instantiate();

        // Start the camera service
        CameraService::instantiate();
    }

    // And now start the Android runtime.  We have to do this bit
    // of nastiness because the Android runtime initialization requires
    // some of the core system services to already be started.
    // All other servers should just start the Android runtime at
    // the beginning of their processes's main(), before calling
    // the init function.
    LOGI("System server: starting Android runtime.\n");
    
    AndroidRuntime* runtime = AndroidRuntime::getRuntime();

    LOGI("System server: starting Android services.\n");
    runtime->callStatic("com/android/server/SystemServer", "init2");
        
    // If running in our own process, just go into the thread
    // pool.  Otherwise, call the initialization finished
    // func to let this process continue its initilization.
    if (proc->supportsProcesses()) {
        LOGI("System server: entering thread pool.\n");
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
        LOGI("System server: exiting thread pool.\n");
    }
    return NO_ERROR;
}

 

 

코드를 보면 알겠지만 크게 다음 순서로 초기화 과정이 이루어진다.

1. Native Service 초기화

SurfaceFlinger

AudioFlinger

MediaPlayerService

CameraService

 

2. Android RunTime 시작

SystemServer

 

안드로이드가 동작하기 위한 여러가지 기본 서비스들(또는 JAVA 서비스)을 시작하는 곳이 SystemServer이다.

 

파일 위치는 다음과 같다.

 

/frameworks/base/services/java/com/android/server/SystemServer.java

 

SystemServer 클래스는 init2() 함수를 호출하게되면 ServerThread를 동작시키고 여기에서 다양한 서비스들을 시작한다.

서비스 시작하는 순서대로 대충 정리하면 다음과 같다.(run 함수의 내용을 그냥 정리한 것이며 * 표시 없는 것은 주서비스이고 * 표시 있는 것은 부가 서비스이다)

 

Power Manager 시작

Activity Manager 생성

 

ActivityManager를 생성해서 context를 받으면 이후 서비스들에는 context를 전달한다.

(아직 이 구조는 잘 모르겠지만 서비스들에서 설정이나 특정 이벤트들을 브로드 캐스팅하기 위해서는 context를 이용해야 하는 것 같다. ActivityManger에서 이를 위한 초기화 과정이 이루어지고 이후 서비스들은 context를 가지고 서로간의 통신이나 Focus 이동이 생길 수 있도록 하고 있는 것 같다. 이것은 아직은 어디까지나 추측이다.)

 

Telephony Registry 시작

Package Manager 시작

System Process로 Activity Manager 설정

Context Manager 시작

System Context Providers 시작

Battery Service 시작

* Hardware Service 시작

Alarm Manager 시작

Sensor Service 시작

 

Window Manager 시작

 

Bluetooth Service 시작

BluetoothDeviceService

BluetoothA2dpService

 

*Status Bar Service 시작

ClipboardService

InputMethodManagerService

 

*NetStat Service 시작

*Connectivity Service 시작

 

*Notification Manager 시작

Mount Service 시작

*DeviceStorageMonitor Service 시작

 

*Location Manager 시작

*SearchManager Service 시작

 *Clipboard Service 시작

*Fallback Checkin Service 시작

*WallpaperService 시작

*Audio Service 시작

*Headset Observer 시작

(?)AppWidgetService

 

*AdbSettingsObserver 시작

(?)HDMISettingsObserver 시작

  


http://blog.daum.net/baramjin/16010975

'Platform > Android' 카테고리의 다른 글

[Android] Init 프로세스 동작  (0) 2010.03.18
[Android] Android 의 개요  (0) 2010.03.18
[Android] Boot Animation  (0) 2010.03.18
[Android] SGL  (0) 2010.03.18
[Android] Surface Flinger의 쓰레드  (1) 2010.03.18

안드로이드의 개요이다.

기본부터 해야하는데 난 이상하게 시작한거 같다. 

========================================================================================================


안드로이드에서 사용하는 언어는 자바이지만 SUN의 자바와 API와 버추얼머신이 다르다. 
Dalvik 이라는 회사의 버추얼머신이 있었는데 구글에서 회사를 통째로 사들였다고 한다. 이때문에 안드로이드는 SUN의 라이센스로부터 자유롭다. 



안드로이드 플랫폼은 크게 네 부분으로 나뉜다. 커널부분, 하드웨어추상레이어, 라이브러리, 응용프로그램 프레임워크. 라이브러리들은 C/C++로 구현이 되어 있다. 기존의 여러 프로젝트 들을 통합하였기 때문에 C로 구현된 것들이 대부분이고 C++도 있다. 응용프로그램 프레임워크는 자바로 구현되어 있다. 프레임워크와 라이브러리 사이에는 자바와 C 사이의 서로다른 호출 규약등을 맵핑하는 JNI라는 마셜러가 존재한다. 하드웨어 드라이버를 C로 만들면 JNI를 구현해야 한다. 이를 위한 구글 가이드가 있고 샘플도 공개되어 있다. 그리고 SDK를 생성하여 응용프로그램 개발자에게 전달하면 된다. 하드웨어 부분은 구글에서 표준으로 정해두었기 때문에 따로 만질 필요가 없다. 추상레이어도 스펙이 다 되어있어 응용프로그램을 개발할 때는 API로 보이게 된다. 
 기존 임베디드리눅스와 안드로이드의 차이점중 한가지는 장치드라이버들( 그래픽, 오디오, 카메라 등 )이 커널영역이 아닌 유저모드에서 동작한다. 유저모드로 동작 시키면 자신에게 할당되어 있는 번지에만 접근할 수 있기 때문에 조금 더 안전하지만 하드에어 제어시에는 MMU등을 참조하는 등의 추가적인 작업이 필요하기 때문에 조금 불편할 수 있다. 이렇게 드라이버들을 유저영역에 넣은 이유는 라이센스문제, 안정성, 문서화의 편리성( 커널버전이 업데이트 될 때마다 드라이버에 대한 문서를 갱신할 필요가 없다 ), 플러그인 방식으로 드라이버 배포가 가능한점이 있다. 안드로이드에서는 기존 리눅스의 라이브러리로 만든 것들은 동작하지 않는다고 보면 된다. 같은 이름의 라이브러리라 할지라도 안드로이드의 라이브러리들은 스마트폰에 탑재하는 것을 기준으로 불필요한 코드들을 제거하고 최적화를 해두었기 때문이다. POSIX Thread 관련 라이브러리를 예로 들면 create, join 등의 필수 함수를 제외한 나머지함수는 모두 제거되어있다. 

Android Kernel

왜 안드로이드는 리눅스 커널 기반일까. 생각하기 나름이겠지만 우선 오픈소스이고 안전하게 입증된 드라이버 모델(well abstracted )이 적용되어 있고, 메모리 프로세스 관리 모델을 제공하고, 하드웨어와 입출력에 대한 보안모델을 제공하고, 공유라이브러리를 지원하는 등 비용과 시간이 적게 드는 이유가 한몫 한것 같다. 

현재 커널 안정화버전은 2.6.27 이다. 구글에서 순수 리눅스 커널을 가져다가 안드로이드 용으로 패치한 것이다. 기존의 리눅스와는 다르게 GLIBC를 지원하지 않고 EABI( Embedded Arm Binary Interface?)와 Binder를 사용한다. 그리고 커널 기능 향상을 위해 Alarm, Ashamem(공유메모리), Low memory-killer, debugger, logger 컴포넌트가 추가되었다. 

유저모드는 허가된 자원에만 접근이 가능하고 프로그램의 안정성을 높일 수 있지만 하드웨어 효율성은 떨어질 수 있다. 반대로 커널모드는 하드웨어 효율성은 높지만 안정성은 떨어질 수 있다. 안드로이드는 기본 드라이버들을 제외한 나머지 드라이버들은 유저스페이스에서 동작한다. 일반 PC는 사람의 생명을 빼았지는 않지만, 심장박동 컨트롤러, 핸드폰만 가지고 조난 당했을 경우와 같이 스마트폰을 모델로 하면 생명과 연결될 수 있기 때문에 안정성이 속도나 효율보다 더 중요하다. 
 
이전에는 일반적으로 일반 gcc를 썼지만 최근의 리눅스 커널을 빌드할 경우에는 ARM사에서 표준으로 정해둔 ABI( arm binary interface ) 규격의 컴파일러를 사용한다. 현재 안드로이드는 EABI( Extended??..) 기능을 지원한다. 일반 컴파일러에서 빌드한 것을 EABI에서 실행할 수 없기 때문에 EABI 컴파일러로 다시 빌드해야 한다. 최근의 임베디드 컴파일러는 대부분 EABI컴파일러 이다. 실수 연산방식에 있어서 하드플로팅포인트와 소프트웨어 플로팅포인트를 혼합하여 빌드할 수 있다. 기존의 ABI는 빌드옵션에서 VFP(Vector Floating Point)를 선택하거나 해제할 수 있었는데 이는 환경이 달라지면 다시 빌드 해야하는 단점이 있었다. EABI는 혼용이 되기 때문에 빌드의 부담이 줄어든다. 또한 구조체 팩킹이 편해졌고 호환성이 증가하였다. 그리고 syscall 규약에 변경사항이 있다. 이전에는 전달인자 4개까지는 레지스터를 쓰고 5개부터는 스택을 사용했는데 레지스터를 r0, r1, r2, r4 처럼 연속된 순서로 했었다.  EABI는 레지스터 간격이 달라지는등 호출 규약이 달라졌다. 

Kernel Enhancement

기존의 임베디드 리눅스에 없던 안드로이드만의 향상된 기능에는 알람, 로우메모리킬러, 공유메모리드라이버, 커널디버거, 바인더, 파워매니지먼트, 로거가 있다. 결국 포팅 이슈는 이것들과 관련될 것이다. 스마트폰으로 만들다 보니까 알람이 기본적으로 제공되어야 한다. 포팅 시 이 기능을 사용하고 싶지 않다면 다른기능과 맞물려 있기 때문에 확인해보고 작업을 진행해야 한다. 공유메모리드라이버는 안드로이드에서 커스터마이징을 했고 메모리 할당이 필요하면 전부 ashmem에 있는 라이브러리를 이용한다. 
리눅스에서는 각 프로세스마다 우선순위를 주고 메모리가 부족하면 우선순위가 낮은 것을 없앤다. 안드로이드는 프로세스마다 우선순위를 주지 않고 그룹마다 우선순위를 준다. 그 이유는 바인더 때문이다.  메모리 부족 시 우선순위가 낮은 그룹을 제거한다. 안드로이드에는 프로그램 종료 기능이 없다. 화면은 내릴 수 있지만 알아서 프로그램이 제거되기 때문이다. 자바로 응용프로그램을 만들기 때문에 가비지컬렉터가 있다. 종료버튼이 있다 하더라도 UI가 없어질 뿐 그 자체가 바로 종료되는 것은 아니다.
이중 가장 중요한 것은 바인더라고 할 수 있다. 바인더에 의해 안드로이드와 기존 리눅스의 차이가 생긴다. 커널버전 2.6.30이상부터는 커널과 안드로이드가 통합된다는 말이 있는데 2.6.29이전의 커널은 바인더폴트( 메모리 회수에 문제가 있는 버그)가 있었다. 그럼 기존에 나왔던 안드로이드폰들도 이 버그가 있었을까? 아마도 개발인력이 많기 때문에 자체적으로 해결했을 것 같다. 바인더 서비스를 넣으면 기존의 전통적인 커널구조가 객체지향 구조로 바뀐다. 컴포넌트 중심으로 양쪽간 메시지를 주고받는 구조로 바뀐다는 말이다. 이것의 장점은 한쪽이 잘못 되어도 반대쪽까지 잘못되지는 않는다는 점. 응답을 못받거나 결과만 이상하게 나올 뿐이다. 
전원관리기능은 기존의 리눅스가 가지고 있는 3단계에 2개를 더해 5단계로 이루어진다. 안드로이드 커널을 설정할때는 자신의 하드웨어에 전원관리 모듈이 없어도 반드시 포함시켜야 한다. 포팅을 하게 되면 시간이 지날수록 이것들에 집중해야 할 것이다. 

Binder


바인더는 프로그램과 데이터를 공유하기 위한 것이다. 기존의 IPC는 보안이슈와 오버헤드이슈가 있다. 리눅스에서도 오픈바인더를 쓸 수 있지만 안드로이드에서 더 활성화를 시켜 두었다. 2.6.29에 기존 버그들이 완벽하게 패치되었다. 이전의 방식은 커널을 통해서 데이터를 공유하였다.(커널의 공유메모리 영역에 데이터를 올려두고 시그널등의 이벤트를 받아 메시지 큐 등을 써서 - 세마포어, 뮤텍스, 스레드 등 ). 바인더는 커널쪽의 메인호스팅이 없고 바인드라는 서비스가 있는 것이다. 바인드를 호출하면 응용프로그램과 디바이스쪽에 바인드서비스가 붙어 서로 통신하게 된다. 바인드서비스는 커널이 아니다. 서로다른 서비스간, 응용프로그램간 데이터를 주고받을 때 동작하게 된다. 여기서의 단점은, 기존의 방식은 하나의 매개체가 있고 공유해서 썼지만 바인드는 각각의 서비스마다 바인더가 있어야 하기 때문에 메모리 낭비가 되는 측면이 있다. 그럼에도 불구하고 쓰는 이유는 바인더는 각각 별개로 동작하기 때문에 주고 받는 통신을 가로챔 당할 가능성이 더 낮아지므로 보안성이 더 오르기 때문이다. 메모리 낭비를 줄이기 위해 바인더를 230kb정도의 크기로 최소화 시켰다. 바인더는 원래 PalmOS에 있던 것이기 때문에 라이센스가 있다. 약 3000라인정도 된다. 
바인더는 스레드 풀을 유지한다. 드라이버, 매니저 서비스마다 바인더가 양쪽에 붙게 되는데 풀로 관리한다는 것은 요구가 있기 전에 미리 자료구조화 시켜 자원을 확보해 두고 바로 맵핑해서 쓸 수 있도록, 바인드 하는데 시간이 걸리지 않도록 되어 있다.  응용 A가 B 디바이스드라이버와 통신을 하게 되면 채널이 생성되는데 만약 채널안에 연결되는 프로그램이 A 이외에 C도 존재 한다면 B가 종료되었다고 해서 바인더가 종료되면 안된다. 이를 위해 참조계수가 있어서 참조계수가 0이 되면 바인드서비스를 해제한다. 

Low Memory Killer
리소스가 부족할 때 자동으로 실행된다. 안드로이드는 그룹 당 우선순위를 주어 해당되는 그룹을 한번에 해제한다. 그룹은 참조계수랑 연관이 있다.  ( 아마도 참조계수가 0 인 것들이 먼저 해제 될듯. ) 
아래 그림은 Low Memory Killer 소스의 일부분이다. 프로세스가 실행되면 프로세스테이블에 등록되어 관리가 된다. 메모리 부족현상이 생기면 shirink 함수가 실행되어 링크드리스트로 되어있는 프로세스컨트롤 블록들을 끝까지 탐색한다. 제거되어야 할 프로세스가 있으면 SIGKILL을 전송한다. 


Power Management 
기존 리눅스드라이버의 파워매니저에 계층을 하나 더 올렸다. 보통 핸드폰은 5단계를 사용한다. 키보드-액정-CPU 순으로 전원이 차단되면서 제일 마지막은 D램에만 전원을 공급하는 상태가 된다. 전원은 CPU가 아닌 PMIC라는 전원공급칩이 제어를 한다. D램에만 전원이 공급되는 상태라도 터치스크린은 잠기지 않는다. 이 상태에서 발생하는 인터럽트도 PMIC가 관리한다. 

Native Libraries

기존의 라이브러리를 그대로 사용하지 않고 EABI로 빌드된 라이브러리이다. 기존의 리눅스는 PC가 모태이기 때문에, 스마트 디바이스환경을 위해 만들어진 것이 아니기 때문에 arm또는 스마트디바이스에 최적화 되어 있지 않다. 바인더가 있고 자바의 JNI를 통해 C코드와 연결되기 때문에 필수적으로 사용되는 C라이브러리 사이즈를 줄이고 효율을 더 좋게 하였다. 안드로이드의 네이티브 라이브러리는 Bionic Lib이라고 부른다. 임베디드 리눅스쪽 라이브러리를 안드로이드로 가져오면 동작하지 않는다. 대부분이 BSD 라이센스기 때문에 코드공개의 의무가 없다. 그리고 프로세스마다 로드 되므로 작은 사이즈( libc.so 사이즈 231Kb )로 되어 있고 경량 pthread가 구현되어 있다. 모든 Native 코드는 bionic과 함께 컴파일 되어야 한다. 웹킷은 오픈소스 브라우저 기반이다. 애플의 사파리, 노키아의 심비안에 이미 적용되어 성능은 검증되어 있다. 브라우저 속도가 아주 빠른것이 특징이다. HTML 표준을 따르고 Active X는 지원하지 않는다. 미디어프레임워크는 PocketVideo OpenCORE 플랫폼 기반이다. 동영상 디코딩을 하며 표준 Video, Audio, Still-frame 포맷을 지원한다. 이를 이용해 상용제품을 양산할 경우 코덱 라이센스에 대한 비용이 발생할 수 있다. SQLite 는 기본 데이터 베이스이다. Mysql과 거의 유사하다. 위치기반 서비스등을 할 때 유용하게 쓰일 수 있다. 
Surface Manager는 모든 응용프로그램의 surface rendering을 프레임버퍼로 전달한다. 프레임버퍼는 LCD와 CPU속도에 차이가 있기 때문에  DRAM 또는 SRAM에 똑같은 구조를 만들어 두고 메모리 블록 전체를 복사해서 한번에 LCD에 출력한다. 이 때 그 메모리 공간을 프레임버퍼라고 한다. 기존의 임베디드리눅스는 2D, 3D를 따로 처리했지만 이 경우에는 동시에 2D, 3D를 처리한다. 화면 합성이나 결합, 반투명 효과등을 한번에 처리할 수 있다. 2D는 단일버퍼로 충분하지만 3D는 데이터량이 많아 단일버퍼로는 병목현상이 생길 수 있기 때문에 프레임버퍼를 더블프레임을 쓴다.  기존의 버퍼 사이즈를 두배로 늘려주면 된다. 더블버퍼링을 2D에도 적용하면 전경그림과 배경그림을 별도로 관리할 수 있어 오버헤드가 줄어든다. 

Audio Manager는 오디오 처리를 한다. 오디로 출력 라우팅 기능이 구현되어 있다. 이전에는 OSS를 사용했는데 안드로이드에서 제대로 동작하지 않기 때문에 ALSA를 써야한다. 기본적으로 ALSA는 디폴트 볼륨이 0 으로 설정되어 있기 때문에 테스트를 하기 위해서는 init 부분에서 볼륨설정을 먼저 해줘야 한다. 

Android Runtime
 

SUN의 자바는 명령들이 전부 8비트 길이를 가지지만 안드로이드는 4바이트이다. 기존의 SUN은 명령어가 스택에 들어가기 때문에 PUSH,POP명령어를 쓰고 Dalvik은 뱅크드레지스터를 이용한 복사명령을 이용하고 레지스터에서 바로 실행시키기 때문에 속도가 더 빠르다. 4바이트가 레지스터에 전부 들어가기 때문에 낮은사양에서도 느려지지 않는 효과도 있다. 프로그램동작은 자바코드이고 드라이버들은 대부분 C/C++이지만 그 사이에 JNI가 있기때문에 동작이 가능하다. JNI는 자바코드에서 C나 C++  라이브러리를 호출할 수 있도록 만들어진 규약이다. 안드로이드에서 응용프로그램은 C/C++로도 만들 수 있다. 대신 UI를 가지기는 힘들다. 백그라운드 서비스를 제작할 경우 굳이 자바로 할 필요는 없다.

HAL ( Hardware Abstraction Layer )

예전에는 하드웨어 드라이버를 하드웨어 제작자가 만들었지만 요즘은 추상계층을 두어 상위 드라이버나 하위 네이티브 드라이버를 서로 독립적으로 개발할 수 있고 응용프로그램도 독립적으로 동작할 수 있다. 이는 일관된 함수 이름과 형식이 있기때문에 가능하다. 개발자가 구현하기 쉽게 표준화된 API들이 존재하며 모든 제조사가 자신의 컴포넌트를 안드로이드 플랫폼에 넣을 수 있도록 구성되었다. HAL은 라이센스문제를 피하고 안정성을 위해 유저스페이스에 존재한다. 

Application Framework
액티비티 매니저는 응용프로그램의 생명주기를 담당한다. 패키지 매니저는 시스템에서 동작중인 응용프로그램들의 정보를 담당한다. 윈도우 매니저는 모든 응용프로그램과 관련된 화면을 담당한다. 뷰 시스템은 표준 위젯을 담당한다. 처음 바탕화면이 위젯이다. 윈도우는 dll 파일이 많지만 안드로이드는 하나의 패키지 파일로 되어있어 프로그램 배포가 쉽다. 

Bootup Sequence

리눅스는 기본적으로 init이 가장먼저 실행된다. init.rc 라는 이름의 파일에는 init이 해야할 작업들이 기록되어 있다. 파일시스템 마운팅, 폴더 권한설정, 캐시폴더 삭제, 시작프로그램 동작 등이 기록되어 있다. 우선 데몬을 올린다. 데몬은 init에 의해 리눅스와 같이 시작되었다가 리눅스가 종료될 때 없어지는 프로그램으로서 데몬을 작성하는 규격에 따라 만들어져야 한다. Zygote가 Dalvik을 초기화 한다. C 밑에 있는 기본라이브러리들은 런타임을 통해 실행되고 상위 서비스들은 Dalvik을 통해 실행된다. 이러한 과정들을 위한 설정은 해당하는 config 파일을 수정하면 된다. 어떤 동작들을 바꾸고 싶으면 기본적으로 init.rc를 바꾸면 되고 Zygote를 바꾸고 싶으면 그 설정파일을 바꾸면 된다. 그리고 시스템서버, 서페이스매니저, 오디오매니저들이 올라간다. 그 다음에는 시스템 서비스들이 활성화 된다. 이들은 서비스이므로 서비스매니저에 등록된다. 

Bootup Sequence - Zygote
Zygote가 실행되면 시스템 서비스가 활성화 된다. 응용프로그램에서는 android.process.* 을 가지고 접근할 수있다. Zygote와 시스템서버간에는 IPC 소켓으로( 127.0.0.x ) 통신을 한다. 

< 부팅 완료 후 각 프로세스들의 상태 >
Android Internals Reference
http://code.google.com/intl/ko/android/
http://groups.google.com/group/android-internals
http://www.android-internals.org/
http://groups.google.com/groups/profile?enc_user=_EKOshMAAADzFnauhYxa0ga8JtF8CI5fWMj6vob75xS36mXc24h6ww
http://groups.google.com/groups/profile?enc_user=lYDbNxEAAAD8uJiqPP7Wd-bc9b1O3waCkdEasx1kiYTQavV7mdW13Q

'Platform > Android' 카테고리의 다른 글

[Android] Init 프로세스 동작  (0) 2010.03.18
[Android] Android 부팅  (0) 2010.03.18
[Android] Boot Animation  (0) 2010.03.18
[Android] SGL  (0) 2010.03.18
[Android] Surface Flinger의 쓰레드  (1) 2010.03.18

+ Recent posts