2015.03.24 14:58


디바이스 트리 작성법 (1편)

이 문서는 디바이스 트리 작성법을 설명한 
http://devicetree.org/Device_Tree_Usage  웹 문서를 번역 및 의역한 것입니다. 
오역 및 잘못된 내용이 있을 수 있습니다. 

제목 : 디바이스 트리 작성법

이 문서는 새로 만들 하드웨어에 대한 디바이스 트리를 어떻게 작성하는지를 다룹니다. 

이 문서가 작성된 목적은 디바이스 트리에 대한 개념을 설명하고 디바이스 트리에 디바이스를 
어떻게 표현하는 가를 설명한 것입니다. 
이 문서는 가장 기본적인 내용만 다루고 있기 때문에 
더 자세한 디바이스 트리의 데이터 포맷이 알고 싶다면 ePAPR 기술 설명서를 참고 하는 것이 좋습니다. 

목차

1. 기본 데이터 형식
2. 기본적인 개념
2.1 장치예
2.2 최초 구조체
2.3 CPU들 
2.4 노드 이름들 
2.5 디바이스들 
2.6 compatible 속성 이해하기 
3. 주소지정 방법
3.1 CPU 주소 지정
3.2 장치 메모리 맵
3.3 메모리 맵에 대상이 안되는 장치들 
3.4 주소 변환 범위들
4.  인터럽트 처리 방법
5.  디바이스 표현 데이터
6.  특별한 노드들 
6.1 별칭 노드들 
6.2 선택 노드
7 조금더 복잡한 주제들
7.1 복잡한 장치 예
7.2 PCI 호스트 브릿지
7.2.1 PCI 버스 번호 매기기
7.2.2 PCI 주소 변환
7.3 복잡한 인터럽트 맵핑
8 참조할 만한 것들 

본문 

1 기본 데이터 형식

디바이스 트리는 노드들로 구성된 트리 구조를 갖습니다.
노드는 또 다른 노드들과 property 라고 불리는 속성을 갖습니다. 
속성은 키 와 값으로 구성된 한쌍으로 이루어져 있습니다. 
예를 들어, 아래는 .dts 확장자가 붙은 파일의 간단한 트리의 내용이다. 
아래에 내용은 보통 확장자가 dts로 붙는 파일에 디바이스 트리를 코딩한 예 입니다. 
/ {
node1 {
a-string-property = "A string";
a-string-list-property = "first string", "second string";
a-byte-data-property = [0x01 0x23 0x34 0x56];
child-node1 {
first-child-property;
second-child-property = <1>;
a-string-property = "Hello, world";
};
child-node2 {
};
};
node2 {
an-empty-property;
a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
child-node1 {
};
};
};
이 코드는 실제로 사용할 수 있는 것은 아닙니다. 
디바이스 트리의 표기법을 설명하기 좋게 만든 임의의 코드입니다. 
위 예에서 
"/" 는 디바이스 트리에 표현하고 싶은 전체 장치의 최상위 루트 노드라는 의미를 갖습니다. 
이후에 설명하겠지만 노드는 다음과 같은 가장 기초적인 형태를 가지고 있습니다. 
노드명 { 노드에 대한 내부 내용 };
내용이 빈 루트 노드를 표현 하라면 다음과 같이 
/ {  }; 
로 표현하겠죠..
위 예제에서는 이 "/" 노드는 다시 "node1" 과 "node2"라는 두개의 자식 노드를 가지고 있습니다. 
이걸 정리하면 다음과 같이 표현 할 수 있습니다. 
/ {  
node1 {  };
node2 {  };
}; 

"node1" 은 "child-node1" 과 "child-node2" 라는 자식 노드를 가지고 있고 , 
"node2" 는 "child-node1" 만을 가지고 있습니다. 
위 예를 이 부분만을 정리하면 다음과 같이 표현 할 수 있습니다. 
/ {  
node1 {  
child-node1 {
};
child-node2 {
};
};
node2 {  
child-node1 {
};
};
}; 
노드는 자식 노드뿐만 아니고 속성을 가질 수 있습니다. 
속성은 키와 값으로 구성된 한 쌍입니다.

키는 반드시 있어야 하지만 키에 대한 값은 없을 수 도 있고,

만약 있다면 임의의 바이트 배열 입니다. 
속성의 형식은 다음과 같습니다. 
키 = 값;
'= ' 앞에 키에 대한 아스키 문자열 형태로 표현합니다 
'=' 뒤에 값에 대한 표현 방법은 뒤쪽에 다시 설명합니다. 
이런 키값의 실제 코딩 예는 다음과 같습니다. 
compatible = "arm,cortex-a9";
속성 값에 대한 데이터 형은 따로 정의 되어 있지 않습니다. 
그러나 디바이스 트리를 편집하고 제작자나 다른 사람이 알아 보기 위해서 몇가지 표현 방법을 사용합니다. 
실제 디바이스 트리의 파일이 컴파일 되어 디바이스 트리의 바이너리 데이터에는 
속성값은 순수하게 이진 바이트 배열의 값들일 뿐입니다. 
이 바이트 배열 값을 해석하는 것은 이 디바이스 트리를 사용하는 운영체제가 알아서 해석해야 합니다. 

이제 속성 값을 기술하기 위한 가장 기본적인 표현 방법을 알아 보겠습니다. 
속성 값에 NULL 로 끝나는 문자열을 쓰고 싶다면 쌍 따옴표를 사용하여 문자열을 표현합니다. 
다음이 그 예 입니다. 
string-property = "a string"
32비트 부호없는 정수형은 "<" 와 ">"를 이용하여 표현합니다. 다음이 그 예 입니다. 
cell-property = <0xbeef 123 0xabcd1234>
이진 데이터는 "[" 와 "]" 를 이용하여 표기한다. 다음이 그 예 입니다. 
binary-property = [0x01 0x23 0x45 0x67];
위의 세가지를 혼합해서 속성값을 표현할때는 각 데이터 표현형태를 ',' 를 사용해서 분리하여 하나의 값으로 표현 할 수 있습니다. 
다음이 그 예 입니다. 
mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;
',' 는 여러 문자열을 나열할때도 사용할 수 있습니다. 다음이 그 예 입니다. 
string-list = "red fish", "blue fish";

2.  기본적인 작성법

디바이스 트리를 어떻게 작성하는지를 설명하기 위해서, 
간단한 샘플 장치를 예로 하여 단계별로 디바이스 트리를 만들어 가 보겠습니다. 
2.1 디바이스 트리를 설명할 샘플 장치 소개

앞으로 만들 디바이스 트리를 위해서 ARM versatile 와 비슷한 임베디드 보드를 가정하겠습니다. 
제작사는 Acme 라는 회사이고 보드 이름은 "Coyote's Revenge" 라고 하죠.
이 보드는 한개의 32 비트 ARM CPU 프로세서로 구성되고
이 프로세서의 로컬 버스에는 시리얼 포트와 SPI 버스 컨트롤러, I2C 컨트롤러, 인터럽트 컨트롤러 및 외부 버스 브릿지가 있고
각각은 로컬 버스 메모리에 맵핑 되어 있다고 가정합니다. 
메모리는 256MB 크기의 SDRAM 이고 0 번지에 맵핑되어 있습니다.
2 개의 시리얼 포트는 0x101F1000 번지와 0x101F2000 번지에 맵핑되어 있습니다.
GPIO 컨트롤러는 0x101F3000 에 주소가 맵핑 되고
SPI 컨트롤러는 0x10170000 에 주소가 맵핑 됩니다. 
이 SPI 컨트롤러에는 여러 디바이스가 SPI 하부 버스에 연결되어 있다고 가정합니다. 

MMC 슬롯도 있는데 MMC 슬롯의 SS 핀은 GPIO #1 에 연결되어 있다고 가정합니다. 
외부 버스 브릿지에는 
SMC 사의 SMC91111 이더넷 장치가 외부 버스에 0x10100000 주소로 맵핑되어 연결되어 있습니다.
또한 I2C 컨트롤러도 0x10160000에 맵핑되어 있고 
이 I2C 컨트롤러의 I2C 버스에 Maxim DS1338 리얼타임클럭이 
슬레이브 주소 1101000 (0x58) 으로 할당되어 연결되어 있다고 가정합니다. 
64MB NOR 플래쉬도 외부 버스에 0x30000000에 주소가 맵핑되어 연결되어 있다고 가정합니다. 

2.2 최초 구조

앞에서 가정한 보드에 대한 디바이스 파일을 작성하기 위해서 
가장 처음 만들 형태는 다음과 같습니다. 

이 구조는 디바이스 트리의 최소한의 형태가 됩니다. 
루트 노드로 표현하면 앞에서 설명했듯이 다음과 같은 형태가 됩니다. 
/ { };
보드 자체가 이 노드인 것이죠..
뒤에서 설명하겠지만 '/' 가 노드 이름입니다. 여기서는 보드 전체를 의미하는 "루트" 가 이름이 됩니다. 
'/'는 디바이스 트리에 딱 한번만 나와야 합니다.

이제 이 노드에 보드에 대한 고유한 식별자를 지정해야 합니다. 
다음과 같이 샘플 보드에 대한 루트 노드의 식별자를 지정합니다. 
/ {
compatible = "acme,coyotes-revenge";
};

"compatible" 란 속성을 이용하여 우리가 표현하고자 하는 보드에 대하여 기술하고 있습니다. 

compatible 속성은 항상 "제조사,모델" 순으로 문자열 형태로 표현합니다. 

수많은 개발자가 디바이스 트리를 만들기 때문에 동일한 이름들을 사용할 수 있습니다. 
이렇게 동일한 이름을 사용하게 되면 운영체제는 다루려는 디바이스나 보드를 구별할 수 없습니다. 
이런 동일한 이름을 사용하는 것을 네임스페이스 충돌 문제라고 합니다. 
그래서 네임스페이스 충돌 문제를 회피하기 위해서는 제조사명과 함께 장치명을 정확하게 기술하는 것은 매우 중요합니다. 
원칙적을 운영체제는 이 compatible 속성 값을 이용해서 다루고자 하는 디바이스에 대한 정보를 찾아 갑니다. 
보통은 운영체제가 원하는 디바이스에 맞는 정보를 찾을때 compatible 속성 값 전체를 비교해 갑니다. 
그리고 정상적이라면 가장 상위부터 찾기 시작합니다. 
2.3 CPU에 대한 표현
보드 자체에 대한 것을 디바이스 트리에 표현했으므로 해당 보드에 있는 CPU에 대한 내용을 추가 할 것입니다. 
CPU 에 대한 추가는 "cpus" 라는노드 이름을 갖는 노드를 이용해서 표현합니다. 
다음은 ARM Cortex A9 듀얼 코어 시스템일 경우를 표현한 예입니다. 

/ {
compatible = "acme,coyotes-revenge";
cpus {
cpu@0 {
compatible = "arm,cortex-a9";
};
cpu@1 {
compatible = "arm,cortex-a9";
};
};
};
이 예를 보면 cpus 노드는 다시 cpu@0  와 cpu@1 이라는 형식의 이름을 갖는 자식 노드를 가집니다.
이 자식 노드들은 어떤 cpu인가의 정보를 표현하기 위해서 compatible 속성을 사용합니다. 
이 compatible 속성은 앞에서 설명했듯이 "제조사,모델" 형식의 값을 가집니다. 
더 많은 속성들이 각 CPU 노드에 추가될 수 있지만, 지금은 가장 기본적인 개념을 이해하기 위한 것들만 다루겠습니다.

2.4 노드 이름 규칙

위 예에서 각 cpu 의 노드 이름을 보듯이 노드들의 이름을 표현하는 고유의 규칙이 있습니다.

모든 노드는 "이름@장치주소" 와 같은 형태로 표현합니다. 
"@장치주소"는 동일한 디바이스를 나타내거난 동일한 내용을 나타내는 노드가 없다면 생략 가능합니다. 
"/" 난 cpus 가 바로 그런 예 입니다. 
이 형식에서 "이름" 부분은 최대 31 개의 문자 길이를 갖는 간단한 아스키 문자열로 표현합니다.
보통 노드의 이름은 장치의 종류를 나타낼 수 있는 이름으로 짓습니다.
예를 들면
3com 이더넷 아답타를 나타내는 노드는 3com509 이라고 이름짓지 않고 ethernet 이라고 이름을 짓습니다.
노드이름의 "장치주소" 부분은 "이름"이 장치의 종류를 나타내므로 각각의 장치들을 구별하기 위해서 사용됩니다. 

노드 이름에서의 "장치주소"는 단지 노드들이 다른 노드임을 구별하기 위한 용도로 사용됩니다. 
실제로 운영체제에서 디바이스를 다루기 위해서 사용하는 장치 주소는 각 노드의 속성중 reg 속성에 실제 정보가 지정 됩니다. 
하지만 보통은 노드 이름의 "장치주소"의 값과 reg 속성에 지정되는 값을 일치시켜서 사용 합니다. 
reg 속성은 뒷쪽에서 다시 자세하게 설명합니다. 
cpus 에 포함되어 있는 각 cpu 가 여러개이기 때문에 각각의  cpu 노드들은 형제 노드가 됩니다. 
형제 노드들의 이름은 유일해야 하기 때문에 
보통 동일한 이름에 해당하는 디바이스의 주소들을 이용해서 이름을 짓습니다. 
위 예에서는 cpu@0 , cpu@1 과 같이 표현하고 있습니다. 
시리얼 장치가 여러개가 있다면 해당 시리얼 장치의 주소를 이용해서 구별하는 것이 일반적입니다. 
에를 들면 serial@101f1000 , serial@101f2000 와 같은 형식으로 하는 것입니다. 
노드의 이름에 대한 자세한 설명은 ePAPR 기술 설명서의 2.2.1 섹션을 참조하시면 좋습니다. 

2.5 디바이스에 대한 표현 

아래 예는 앞에서 만든 디바이스 트리에 보드에 포함된 디바이스에 대한 노드를 추가 한 예입니다. 
이 예에서는 각 디바이스의 주소나 인터럽트와 같은 내용에 대한 것은 포함하지 않고 있습니다 .
각각의 속성을 설명할때 마다 추가 할 것입니다. 
/ {
compatible = "acme,coyotes-revenge";
cpus {
cpu@0 {
compatible = "arm,cortex-a9";
};
cpu@1 {
compatible = "arm,cortex-a9";
};
};
serial@101F0000 {
compatible = "arm,pl011";
};
serial@101F2000 {
compatible = "arm,pl011";
};
gpio@101F3000 {
compatible = "arm,pl061";
};
interrupt-controller@10140000 {
compatible = "arm,pl190";
};
spi@10115000 {
compatible = "arm,pl022";
};
external-bus {
ethernet@0,0 {
compatible = "smc,smc91c111";
};
i2c@1,0 {
compatible = "acme,a1234-i2c-bus";
rtc@58 {
compatible = "maxim,ds1338";
};
};
flash@2,0 {
compatible = "samsung,k8f1315ebm", "cfi-flash";
};
};
};

이 예로 든 코드는 운영체제가 쓸수 있을 정도로 기술한 내용이 완전하지 않습니다. 
왜냐하면 디바이스를 다루기 위한 필요한 속성들과 
디바이스들 사이의 연결관계에 대한 정보를 아직까지 기술하지 않았기 때문입니다. 
하지만 보드에 디바이스가 어떤 계층 구조를 가지고 있는지를 알 수 있습니다. 

이와 관련된 정보는 곧 추가 될 것이다. 

위 예 중 일부를 설명하면 
external-bus 라고 이름을 갖는 것은 보드가 외부 버스가 있음을 표현하고 있고,
그 외부 버스는 다시 이더넷, i2c 버스, 플래쉬가 있음을 알 수 있습니다. 
각각은 자식 노드로 표현되고 있습니다. 
또한 i2c 버스는 하부에 또 다른 디바이스가 있음을 포함된 자식 노드들로 표현합니다.
보통 보드의 구성 상태를 나타내는 이런 계층 구조는 CPU의 관점에서 보여줍니다. 
위 예는 다음과 같은 것들도 알 수 있습니다. 
- 모든 디바이스 노드는 compatible 속성을 갖습니다. 
- 플래쉬 노드는 compatible 속성에 2 개의 문자열을 포함하고 있습니다. 
왜 이런지는 뒷쪽에서 알려 줄 것입니다.
- 앞에서 언급했듯이, 노드명은 디바이스 타입을 반영하는 것이지 특정한 모델을 지칭하는 것이 아닙니다 
보통 일반적으로 사용가능한 노드의 이름 목록은 ePAPR 기술 설명서 섹션 2.2.2 를 참고하면 알수 있습니다. 
2.6 compatible 속성 사용법
디바이스 트리에 디바이스를 표현하는 모든 노드는 compatible 속성을 가져야 합니다. 
compatible 속성은 운영체제에서 동작하는 디바이스 드라이버가 다룰 디바이스에 대한 정보를 찾기 위한 키 값입니다. 
compatible 은 하나의 문자열만 가지는 것이 아니고 여러개의 문자열들이 나열된 리스트입니다. 
이 문자열 리스트의 첫번째 문자열은 디바이스를 정확하게 구별하기 위해서 
"<제조사>,<모델>" 형식으로 표현해야 합니다. 
첫번째 문자열 이외에는 이런 형식을 따르지 않아도 되며, 보통은 호환 가능한 다른 디바이스를 구별하기 위한 문자열이 됩니다. 
예를 들면,
프리스케일 MPC8349 프로세스는 내부에 National Semiconductor ns16550와 호환 가능한 인터페스를 가지는 시리얼 디바이스를 가지고 있습니다. 
그렇기 때문에 MPC8349 보드를 기술하는 디바이스 트리의 시리얼 디바이스 노드의 compatible 속성은 다음과 같이 표현합니다.
compatible = "fsl,mpc8349-uart", "ns16550"; 
이 보드에서 동작하는 운영체제는 해당 디바이스를 다루는 디바이스 드라이버를 찾기 위해서 
먼저 운영체제는 "fsl,mpc8349-uart" 문자열을 인식할 수 있는 디바이스 드라이버를 찾을 것이고 , 만약 발견에 실패한다면 
"ns16550"의 문자열을 인식할 수 있는 디바이스 드라이버를 찾을 것입니다. 
운영체제의 디바이스 드라이버 구현 방법에 따라서는 
디바이스 드라이버가 자신이 다룰 디바이스 정보를 얻기 위해서 
먼저 디바이스 트리에 제공된 각 노드를 탐색하면서 compatible  속성에 선언된 문자열 리스트에 
"fsl,mpc8349-uart"의 문자열을 포함하거나 "ns16550" 를 포함한 
노드를 발견하면 이에 대한 처리가 진행될 것입니다. 

결국 위 예에서 
"fsl,mpc8349-uart" 라고 기술한 것은 해당 디바이스 자체를 표현한 것이고,
"ns16550" 는 내부 레지스터를 다루는 방법이 National Semiconductor 16550 UART 와 호환 가능하다는 의미이다. 
주의:
위 예에서 "ns16550" 에는 제조사 접두사를 사용하지 않고 있습니다. 

모든 새로운 선언되어 지는 compatible 속성 값은 "mpc8349-uart" 처럼 제조사 접두사를 사용해야 합니다. 
"ns16550"는 이미 널리 알려져 있기 때문에 굳이 제조사 접두사를 붙이지 않은 것입니다. 

하지만 여러분이 작성할때는 반드시 제조사 접두사를 붙여 주어야 합니다. 
이런 룰을 지키는 것이 새로운 디바이스를 처리하는 디바이스 드라이버가 확실하게 연결되는 것을 보장합니다. 
경고:
compatible 의 속성값에 "fsl,mpc83xx-uart" 와 같은 형식으로 와일드 문자를 사용하지 마십시오.
왜냐하면 여러분이 해당 칩셋간에 호환성이 있기 때문에 모두 적용이 가능하다고 믿고 와일드 카드를 사용하여 
기술하시겠지만 나중에 반도체 판매자들은 아마도 이런 가정이 쓸모 없게 할 가능성이 농후 합니다. 
만약 이런 사태가 발생하면 수습이 어렵다는 것을 확신합니다. 
가급적 해당 칩의 정확한 모델명을 사용하십시오.


출처 : http://forum.falinux.com/zbxe/index.php?filter=search&mid=lecture_tip&search_target=title&search_keyword=%EB%94%94%EB%B0%94%EC%9D%B4%EC%8A%A4+%ED%8A%B8%EB%A6%AC&document_srl=784561


신고

'Computer > Linux/Unix' 카테고리의 다른 글

디바이스 트리 작성법 (3편)  (0) 2015.03.24
디바이스 트리 작성법 (2편)  (1) 2015.03.24
디바이스 트리 작성법 (1편)  (0) 2015.03.24
[Linux] Module 관련  (0) 2015.03.13
[Makefile] Kbuild 와 Module Compile  (0) 2015.03.09
[Makefile] Device Driver  (0) 2015.03.09


Posted by injunech
2015.03.20 11:10


아이폰과 안드로이드의 속도 경쟁은 결국 32bit와 64bit 운영체제의 논쟁으로까지 번지는 형국이다. 하지만 그 싸움에서 안드로이드 진영은 애플을 이길 수 없다. 그 이유는 안드로이드의 앱 구동 체계의 구조적 문제 때문이다.


안드로이드는 리눅스 운영체제의 일종이면서도 사용자가 사용하는 앱은 모두 Java 언어로 개발된다. Java로 개발된 앱의 소스파일은 바이트 코드로 컴파일되기 때문에 운영체제가 직접 실행하는 것이 불가능하다. 왜냐하면 Java에서 컴파일된 바이트코드는 java Run-time 이라고 하는 실행환경(가상의 운영체제)에서만 읽고 해석(Just-In-Time 컴파일)이 가능하기 때문이다. 그리고 이러한 역할을 수행하는 것이 안드로이드에서 지원하는 앱구동 환경인 달빅(Dalvik)이다.


하지만 iOS는 앱이 기계어로 컴파일되어 저장소에 파일로 저장되어 있다가 사용자가 앱을 실행하면 곧바로 메모리에 올려져 운영체제에 의해 실행된다. 즉 안드로이드 처럼 앱과 운영체제의 중간에 존재하는 달빅과 같은 JIT 컴파일러가 필요없다. 이런 차이점은 바로 안드로이드의 앱 개발환경이 Java 이고 iOS의 앱 개발환경이 Object-C라고 불리는 C언어 환경이기 때문에 발생하는 차이다. iOS의 오브젝트C는 C언어로 작성된 앱의 소스파일을 아이폰의 운영체제인 iOS가 직접 읽어 메모리에 적재(loading)하고 곧바로 실행할 수 있도록 기계어코드(목적코드 혹은 Object-Code)로 만들어 저장소에 저장된다.


이 두가지 앱 구동 환경을 이해하기 쉽게 표시하면 아래그림과 같다.





간단한 그림의 표현만으로도 "안드로이드 스마트폰이 메모리도 더 크고 CPU도 더 빠른데 왜 아이폰보다 느린지"를 이해할 수 있을 것이다.


안드로이드와 애플의 64bit 전쟁.


앞에서 살펴본 스마트폰의 운영체제와 앱구동환경의 차이로 인해 최근 논란이 되고 있는 64bit 지원 논쟁에서 애플은 64bit 지원에 대해 자신감을 보이고 있는 반면 안드로이드를 만드는 구글은 멈칫하며 주저하는 미묘한 입장차이를 보이고 있기도 하다.


애플은 iOS와 오브젝트C 개발환경 그리고 CPU까지 모두 스스로 만들고 있으며 64bit CPU (AP : Application Processor라고도 부름)개발과 64bit iOS개발, 그리고 64bit 오브젝트C의 개발이 모두 하나의 작업처럼 진행될 수 있기 때문에 현재의 기술로서 64bit를 지원하는 것은 그리 어려운 일이 아니다. 게다가 32bit 오브젝트C로 개발된 앱의 64bit 포팅도 충분히 가능하다.


하지만 구글의 입장은 매우 복잡하다. 


리눅스 운영체제부터 64bit로 전환해야 하고 그 위에서 구동되는 Java는 Oracle에서 만들고 있으며 앱의 개발환경은 또 다른 곳에서 개발되고 있고 앱의 구동환경인 달빅의 64bit 포팅도 여러가지 문제로 인해 쉽지 않은 입장이다. 


여러 자유(?)진영의 합작품인 안드로이드가 64bit 지원이라는 복병을 만나 잠시 주춤하는 모습을 보이고 있다. 어찌보면 구글은 아이폰의 대항마였던 안드로이드를 만들면서 가장 쉬운길이었던 두가지의 선택, 즉 운영체제로서 리눅스를 선택한 것과 개발환경 및 앱 운영환경으로 가장 범용적이고 많은 개발자를 확보할 수 있었던 Java를 선택한 댓가를 64bit 환경의 지원이라는 과제 앞에서 치르고 있는지도 모르겠다.


어쩌면 구글은 64bit 문제로 인해 장기적으로는 안드로이드를 버리는 계획을 내부적으로 수립하고 있을지도 모른다. 그리고 그 대안으로 크롬(Chrome) OS를 밀어줄 것이 확실시 된다.


Dalvik vs ART(Android Run-time)


하지만 구글은 당장 안드로이드를 버릴 수 없기 때문에 현실적인 판단을 할 수 밖에 없다. 그 결과로서 구글은 안드로이드의 앱 구동에 대한 부정적인 이미지를 벗기위해 성능개선에 매달렸고 새로운 앱 구동환경 즉 런타임환경을 새롭게 만들었다.


구글은 최근에 출시한 넥서스5에서 Dalvik을 대체할 새로운 앱의 구동환경으로 내놓은 ART가 그것이다. 보다 빠른 앱의 구동을 지원하는 ART는 이 포스트를 올리는 현재시간 기준으로 넥서스5에서만 사용이 가능하다.



구글이 나름대로 안드로이드의 성능개선을 위해 많은 노력을 하고있긴 하지만 언제까지 지원을 아끼지 않을지는 알 수 없다. 그리고 "리눅스-Java-앱"의 3계층 구조 자체를 뜯어고치지 않는 이상 아이폰의 성능을 쫒아가는 것은 거의 불가능하다고 보여진다.  하지만 그러기엔 너무 먼길을 왔다. 아마도 그래서 구글이 크롬을 밀어줄 것 같다는 생각은 더욱 확실해진다.

신고

'Life > IT' 카테고리의 다른 글

Gear S3 Design  (0) 2017.05.29
Gear S3 시계화면 추천  (0) 2016.12.16
[앱추천] 촛불시위 어플  (0) 2016.11.29
기어 S3 프론티어 개봉&리뷰  (0) 2016.11.16
안드로이드와 아이폰 앱 실행 속도 비교  (0) 2015.03.20


Posted by injunech
2015.03.15 15:02


※ WM_SYSCOMMAND → WM_CLOSE → WM_DESTROY → WM_QUIT


1. WM_CLOSE
   - 윈도우가 닫히기 전에 메시지가 전달 된다.
   - 아직 윈도우가 파괴된 것은 아니므로 윈도우가 파괴되는 것을 중간에 제어 할 수 있다.
   - 윈도우의 “닫기” 를 누르거나, 키보드의 “Alt + F4”를 눌렀을 경우 발생




   - WM_CLOSE 의 핸들러(OnClose) 에서 추가적인 제어를 하지 않는다면 메시지는
      DefWindowsProc 로 보내진다.
   - CDialog::OnClose() 는 내부적으로 DestroyWindow() 함수를 호출 한다.
   - DestroyWindow() 함수는 내부적으로 WM_DESTROY 메시지를 발생 시킨다.


2. DestroyWindow()
   - CWnd내부에 있는 윈도우를 destroy 한다. 
   - 윈도우를 해제하고 입력 포커스를 제거하기 위한 적절한 message를 윈도에게 보낸다. 
   - 윈도우의 메뉴 제거  
   - application queue를 비운다.
   - timer를 제거 
   - Clipboard의 소유주 제거
   - Clipboard-viewer chain을 끊는다. ( CWnd가 viewer chain의 맨 위에 있을 경우 ) 
   - WM_DESTROY(OnDestroy)와 WM_NCDESTROY(OnNcDestroy) 메시지를 윈도우 에게 보낸다.
     하지만 아직 CWnd 객체는 destroy하지 않는다.


3. WM_DESTROY
   - Framework이 CWnd에게 현재 CWnd가 소멸되고 있는 중이라고 알려 주기 위하여 호출 
   - 화면에 윈도우를 숨긴 후 메시지 발생, 아직 윈도우 자체는 파괴되지 않았다
   - DestroyWindows() 함수에서 발생 시킨다.
   - WM_CREATE 에 반대되는 동작을 수행 한다.
   - 차일드 윈도우가 있다면 이 메시지를 차례대로 전달 한다.
   - 메인 윈도우에서 PostQuitMessage() 함수를 반드시 호출하여 프로세스의 메시지 루프
     를 종료시켜야 한다. 그렇지 않다면 윈도우만 파괴되고 메시지 루프는 계속 실행중인
     상태가 되므로 프로세스가 종료되지 않는다.


4. WM_NCDESTROY
   - Client 영역이 아닌 영역이 Destroy 될 때 Framework 에 의하여 불려짐.
   - 윈도우가 소멸될 때 마지막으로 호출되는 메시지
   - 핸들러를 재정의 한다면 기본 호출 함수를 가장 위에서 해주자.

   
5. PostNcDestroy()
   - 윈도우가 소멸된 후 OnNcDestroy() 함수에 의해 불려지는 함수
   - 사용자들이 상속받아 만든 클래스의 정리를 위한 코드를 넣음.


6. View가 닫혀질 때 호출되는 핸들러 순서
BOOL CAniView::DestroyWindow() 

  
// TODO: Add your specialized code here and/or call the base class 
// 윈도우가 안보여 지기전에 해야 할 작업 처리
  
 return CView::DestroyWindow(); 
  

  
void CAniView::OnDestroy() 

  
  CView::OnDestroy(); 
  
  // TODO: Add your message handler code here 
  

  
void CAniView::PostNcDestroy() 

  
  // TODO: Add your specialized code here and/or call the base class 
  
  CView::PostNcDestroy(); 
  
}


7. WM_QUIT
   - 응용프로그램을 종료 하라는 메시지
   - PostQuitMessage() 가 발생 시키는 메시지
   - GetMessage() 함수가 0 을 리턴하도록 함으로써 메시지 루프를 종료
   - PeekMessage() 함수는 따로 WM_QUIT 메시지를 점검해야 한다.





다음과 같이 종료 시킨다.


HWND hWndBuilder;

hWndBuilder = ::FindWindow( NULL, "NxBuilder" );

1번 : if(hWndBuilder!=NULL) ::PostMessage(hWnd,WM_CLOSE,0,0);  --> 정상종료시

2번 : if(hWndBuilder!=NULL) ::PostMessage(hWnd,WM_DESTROY,0,0);  --> 마찬가지

3번 : if(hWndBuilder!=NULL) ::PostMessage(hWnd,WM_QUIT,0,0); --> 강제종료





신고


Posted by injunech