<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>2008. There&#039;s something in the air.</title>
		<link>http://www.v12n.info/</link>
		<description></description>
		<language>ko</language>
		<pubDate>Fri, 12 Dec 2008 11:30:24 +0900</pubDate>
		<generator>Tistory 1.1 (http://www.tistory.com/)</generator>
		<image>
		<title>2008. There&#039;s something in the air.</title>
		<url><![CDATA[http://cfs7.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNy50aXN0b3J5LmNvbTovYXR0YWNoLzAvMC5naWY=]]></url>
		<link>http://www.v12n.info/</link>
		<description></description>
		</image>
		<item>
			<title>Distributing Python Modules</title>
			<link>http://www.v12n.info/19</link>
			<description>&lt;p&gt;Python Module 의 배포를 위해서는 일반적으로 Python Distribution Utilities (&quot;Distutils&quot;) 라는 모듈을 사용하게 된다. 작성한 Python 모듈을 패키지할 필요성이 생겨서 이에 대해서 살펴보면서 정리를 한다.&lt;/p&gt;
&lt;p&gt;1.1 Concepts&lt;/p&gt;
&lt;p&gt;Distutils 를 사용하는 것은 모듈 개발자와 3rd 파티 모듈을 설치하려는 사용자/관리자 모두에게 매우 간단할 일이다. 개발자로서는&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;setup 스크립트를 작성&lt;/li&gt;

  &lt;li&gt;(선택에 따라서는) setup 설정 파일을 작성&lt;/li&gt;

  &lt;li&gt;소스 배포를 생성&lt;/li&gt;

  &lt;li&gt;(선택에 따라서는) 하나 혹은 그 이상의 개발된 배포파일을 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;의 일을 갖게 된다.&lt;/p&gt;
&lt;p&gt;이러한 태스크들의 각각에 대해서 본 문서에서 설명하게 된다.&lt;/p&gt;&lt;p id=&quot;more19_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;19_0&#039;,&#039; more.. &#039;,&#039; less.. &#039;); return false;&quot;&gt; more.. &lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content19_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt; &lt;p&gt;1.2 Simple Example&lt;/p&gt;
&lt;p&gt;setup 스크립트는 일반적으로 매우 간단하다. 특히 python 으로 짜여있기 때문에, 특별한 제약을 갖지 않는다.
Autoconf 스타일의 설정 스크립트와는 달리, setup 스크립느는 개발한 모듈의 배포판을 빌딩 그리고 설치하는 데 있어서
여러번 수행될 수도 있다.&lt;/p&gt;
&lt;p&gt;만약 하나의 foo.py 파일을 갖고 있는 foo 라 불리오는 모듈을 배포하기 위해서는 다음과 같이 setup 스크립트를 작성한다.&lt;/p&gt;
&lt;p&gt;from distutils.core import setup&lt;/p&gt;
&lt;p&gt;setup (name=&#039;foo&#039;,&lt;/p&gt;
&lt;p&gt;version=&#039;1.0&#039;,&lt;/p&gt;
&lt;p&gt;py_modules=[&#039;foo&#039;],&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;살펴봐야 할 점은&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;distutils 에 제공하는 대부분의 정보는 setup 함수에 keyword 아규먼트들로 제공된다.&lt;/li&gt;&lt;li&gt;이러한 키워드 아규먼트들은 두개의 카테고리들로 나뉜다: package metadata (이름, 버전 번호) 그리고 패키지 안에 무엇이 있는지에 관한 정보 (순수한 파이선 모듈들의 목록)&lt;/li&gt;&lt;li&gt;모듈들은 파일의 이름이 아닌 모듈 이름에 의해서 한정된다.&lt;/li&gt;&lt;li&gt;가급적 많은 메타데이터를 제공하는 것을 추천하는데, 특별히 예를 들자면 개발자 이름, Email 주소, 그리고 프로젝트의 URL 등을 들 수 있다.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;이 모듈의 소스 배포판을 생성하기 위해서, 위 코드를 담고 있는 setup 스크립트 setup.py 를 생성한후, 수행한다:&lt;/p&gt;
&lt;p&gt;python setup.py sdist&lt;/p&gt;
&lt;p&gt;이는 윈도에서는 Zip, 유닉스에서는 tarball 형태로 archive 파일을 만드는데, 이는 setup.py 와 모듈
foo.py 를 담게 된다. archive 파일은 foo-1.0.tar.gz (혹은 .zip)이 될 것이고, foo-1.0
디렉토리에 풀리게 될 것이다.&lt;/p&gt;
&lt;p&gt;만약 사용자가 foo 모듈을 설치하기를 원한다면, 사용자가 해야할 일은 foo-1.0.tar.gz 를 다움 받아서 이의 압축을 풀고, foo-1.0 디렉토리에 들어가서&lt;/p&gt;
&lt;p&gt;python setup.py install&lt;/p&gt;
&lt;p&gt;을 수행하는 것이다. 이는 궁극적으로는 사용자가 파이선을 설치한 곳의 3rd 파티 모듈을 위한 적절한 디렉토리에 foo.py 를 카피하게 된다.&lt;/p&gt;
&lt;p&gt;이러한 간단한 예제는 Distutils 의 일부 기본적인 개념을 보여준다. 첫째, 개발자와 설치가 둘다 같은 기본 사용자
인터페이스를 갖는다. 차이라고는 단지 Distutils를 이용할 때 sdist 커맨트를 사용하느냐와 install 을
사용하느냐의 차이이다.&lt;/p&gt;
&lt;p&gt;만약 개발자가 사용자를 위해서 정말 뭔가 더 쉽게 만들어주고 싶다면, 하나 혹은 그 이상의 내장된 배포판을 만들 수 있다.
예를 들어서 개발자가 위도 머신을 사용하고 있을 때, 다른 윈도 사용자를 위해서 더 쉽게 만들어주고 싶다면, 개발자는
bdist_wininst 커맨드를 이용해서 다음과 같이 수행가능한 설치 파일을 만들어줄 수 있다.&lt;/p&gt;
&lt;p&gt;python setup.py bdist_wininst&lt;/p&gt;
&lt;p&gt;위 커맨드는 수행가능한 인스톨러인 foo-1.0.win32.exe 파일을 생성하게 된다.&lt;/p&gt;
&lt;p&gt;다른 유용한 내장된 배포 포맷은 RPM 인데 이는 bdist_rpm 커맨드를 이용하면 된다. 솔라리스의 pkgtool 은 (bdist_pkgtool), HP-UX swinstall (bdist_sdux)를 이용하면 된다.&lt;/p&gt;
&lt;p&gt;다음과 같은 커맨드를 수행해서 어떠한 배포 포맷이 가능하지를 찾아낼 수도 있다.&lt;/p&gt;
&lt;p&gt;python setup.py bdist --help-formats&lt;/p&gt;
&lt;p&gt;1.3 General Python terminology&lt;/p&gt;
&lt;p&gt;module&lt;/p&gt;
&lt;p&gt;Python 에서 코드 재사용의 기본 유닛이 된다. 여기에는 pure Python 모듈, 확장 모듈, 그리고 패키지 세가지 형태가 존재한다.&lt;/p&gt;
&lt;p&gt;pure Python 모듈&lt;/p&gt;
&lt;p&gt;Python 으로 쓰여진 모듈. 하나의 .py 파일에 포함되고 종종 &quot;pure module&quot;이라 불리운다.&lt;/p&gt;
&lt;p&gt;extension 모듈&lt;/p&gt;
&lt;p&gt;Python 구현의 저수준 언어인 C/C++ for Python, Java for Jython 등으로 작성된 모듈.
기본적으로 하나의 동적으로 로딩이 가능한 pre-compiled 파일 (예를 들자면 유닉스에서는 Python 확장을 위한
shared object (.so) 파일, 윈도에서는 .pyd 확장자를 갖는 DLL 파일 Jython 확장을 위한 Hava
클래스 파일)&lt;/p&gt;
&lt;p&gt;package&lt;/p&gt;
&lt;p&gt;다른 모듈을 포함하고 있는 하나의 모듈; 기본적으로 filesystem 에서 하나의 디렉토리를 포함하고 다른 디렉토리와는 __init__.py 파일로 구분된다.&lt;/p&gt;
&lt;p&gt;root package&lt;/p&gt;
&lt;p&gt;package들의 계층에있어서 root. (이는 __init__.py 를 갖지 않기에 진짜 패키지는 아니지만 일반적으로 그렇게 부르곤 한다.)&lt;/p&gt;
&lt;p&gt;1.4 Distutils-specific terminology&lt;/p&gt;
&lt;p&gt;다음 용어들은 Distutils를 이용해서 배포되는 Python 모듈들에 대해서 적용된다.&lt;/p&gt;
&lt;p&gt;module distribution&lt;/p&gt;
&lt;p&gt;하나의 다운로드가 가능한 자원으로서 같이 배포되는 파이션 모듈들의 집합으로 한꺼번에 설치되는 것을 의미. 일부 잘 알려진 모듈 배포판의 예로는 Numeric Python, PyXML, PIL 혹은 mxBase가 있다.&lt;/p&gt;
&lt;p&gt;pure module distribution&lt;/p&gt;
&lt;p&gt;오직 pure Python 모듈들과 패키지들을 담고 있는 하나의 모듈 배포판. 종종 pure distribution 이라고도 불림&lt;/p&gt;
&lt;p&gt;non-pure module distribution&lt;/p&gt;
&lt;p&gt;적어도 하나의 extension 모듈을 담고 있는 모둘 배포판. 종종 non-pure distribution 이라고도 불림&lt;/p&gt;
&lt;p&gt;distribution root&lt;/p&gt;
&lt;p&gt;개발한 소스트리의 최상의 디렉토리; 디렉토리는 setup.py 가 존재하고 일반적으로 해당디렉토리에서 setup.py 가 수행된다.&lt;/p&gt;
&lt;p&gt;2. Writing the Setup Script&lt;/p&gt;
&lt;p&gt;setup script 는 Distutils 를 이용해서 모듈을 생성, 배포, 설치하는 데 있어서 모든 행동의 중심이
된다. setup script의 주 목표는 개발한 모듈 배포판을 Distutils에게 기술하기 위함히고, 그래서 개발한 모듈에
대해서 적절한 일을 하는 다양한 커맨드들을 갖고 있다. 1.2 에서 기술된 바와 같이, setup script 는 주로
setup() 을 호출하는 것으로 구성되고, 모듈 개발자에 의해서 Distutils에 제공되는 대부분의 정보는 keyword
arguments 로 setup() 에 제공된다.&lt;/p&gt;
&lt;p&gt;다음은 다음 두 섹션에서 살펴보게된 간단한 예제이다.&lt;/p&gt;
&lt;p&gt;#!/usr/bin/env python&lt;/p&gt;
&lt;p&gt;from distutils.core import setup&lt;/p&gt;
&lt;p&gt;setup(name=&#039;Distutils&#039;,&lt;/p&gt;
&lt;p&gt;version=&#039;1.0&#039;,&lt;/p&gt;
&lt;p&gt;description=&#039;PythonDistribution Utilities&#039;,&lt;/p&gt;
&lt;p&gt;author=&#039;Greg Ward&#039;,&lt;/p&gt;
&lt;p&gt;author_email=&#039;gward@python.net&#039;,&lt;/p&gt;
&lt;p&gt;url=&#039;http://www.python.org/sigs/distutils-sig/&#039;,&lt;/p&gt;
&lt;p&gt;packages=[&#039;distutils&#039;, &#039;distutils.command&#039;],&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;여기에서 제공된 예제는 1.2 에서 제공된 예제와 두가지 차이점을 가지고 있다. 더많은 메타데이터가 사용되었고, 모듈보다는
패키지에 의해서 pure Python 모듈들이 기술되었다. 이러한 부분은 중용한 부분으로 Distutils 가 두개의 패키지들에
여러모듈로 구성되어 있다. 모든 모듈들의 목록을 유지하기란 많들기도, 유지하기도 힘들 일이다. 더 자세한 내용을 원한다면 2.8
장의 추가적인 메타 데이터를 보기 바란다.&lt;/p&gt;
&lt;p&gt;setup script 에 제공되는 어떠한 패스이름들 (파일이름 혹은 디렉토리 이름)은 Unix 컨벤션을 이용해서
작성되어야 한다. Distutils 는 실제로 사용하기 전에 이러한 플랫폼 중립적 표현을 당신이 사용하고 있는 플랫폼에 맞추어
변환하게 된다. 이는 setup script 가 운영체제에 구애받지 않고 이식성을 갖게 해준다. 이에 따라서 본 문서의 모든
패스이름들은 / 로 구분되어 질 것이다.&lt;/p&gt;
&lt;p&gt;물론 이는 Distutils 함수에 제공되는 패스이름에만 적용된다. 예를 들어, 당신이 팡일을 언급하기 위해서
glob.glob() oros.listdir()와 같은 표준 Python 함수들을 사용한다면, 하드코딩된 패스 구분자보다는
이식가능한 코드를 작성하도록 주의해야 한다.&lt;/p&gt;
&lt;p&gt;glob.glob(os.path.join(&#039;mydir&#039;, &#039;subdir&#039;, &#039;*.html&#039;))&lt;/p&gt;
&lt;p&gt;os.listdir(os.path.join(&#039;mydir&#039;, &#039;subdir&#039;)&lt;/p&gt;
&lt;p&gt;2.1 Listing whole packages&lt;/p&gt;
&lt;p&gt;패키지들 옵션은 Distutils 에게 패키지들 리스트에서 언급된 각각의 패키지에서 찾을 수 있는 모든 pure
Python 모듈들에 대해서 어떠한 처리를 할 지 말하게 된다. 이를 위해서, 물론, 패키지 이름과 파일시스템상에서의
디렉토리간의 대응점이 있어야만 한다. 기본 대응점은 가장 명확한 것 (예를 들어 distutils 패키지는 배포판 루트에 대해서
distutils 디렉토리안에서 찾을 수 있다.)이 된다. 그러므로, 개발자가 packages = [&#039;foo&#039;] 라고 setup
script 에서 언급했을때, 개발자는 Distutils 에게 setup script 가 존재하는 디렉토리를 기반으로
foo/__init__.py를 찾을 수 있다고 약속하는 것과 같은 것이다. 만약 개발자가 이 약속을 저버린다면,
Distutils 는 warning 을 발할 것이고, 깨진 패키지를 생산하게 된다.&lt;/p&gt;
&lt;p&gt;만약 개발자가 소스디렉토리의 구조레 대해서 다른 컨벤션을 사용하고 싶다면, 이를 지원하지 위한 방안이 있다: 개발자는 단지
package_dir 옵션을 이용해서 원하는 컨벤션을 이야기하면 된다. 예를 들어, lib 아래의 모든 Python 소스를
유지하고 싶다면, 그래서 해당 모듈들이 어떠한 패키지에도 속하지 않는 &quot;root package&quot; 가 lib 안에 있고, foo
패키지안의 모듈들이 lib/foo에 있다면.. 등일때 setup script 에서 다음과 같이 package_dir 을 사용한다&lt;/p&gt;
&lt;p&gt;package_dir = {&#039;&#039;: &#039;lib&#039;}&lt;/p&gt;
&lt;p&gt;이 사전의카들은 패키지 이름들과 root 패키지를 위한 공란의 패키지 이름이다. 값들은 배포판 root 의 상대적인
디렉토리 이름이 된다. 이 경우에는, pckages = [&#039;foo&#039;]라고 말한다면, 개발자는 lib/foo/__init__.py
가 존재함을 약속하는 것이다.&lt;/p&gt;
&lt;p&gt;또다른 가능한 컨벤션은 lib 바로 아래 foo 패키지를 넣고, foot.bar 패키지를 lib/bar 에 넣는 것이다. 이를 위해서는 setup script 는 다음과 같이&lt;/p&gt;
&lt;p&gt;package_dir = {&#039;foo&#039;: &#039;lib&#039;}&lt;/p&gt;
&lt;p&gt;와 같이 기술되어야 한다. package_dir 사전 안의 package: dir 엔트리는 묵시적으로 package 아래의
모든 패키지들에 적용된다. 그래서 foo.bar 경우는 자동적으로 이에 의해서 다루어진다. 이 예제에서, packages =
[&#039;foo&#039;, &#039;foo.bar&#039;]를 갖는 것은 Distutils 에게 lib/__init__.py와
lib/bar/__init__.py 를 살펴보라고 말하게 되는 것이다. (명시해야 할 것은 package_dir 이 순환적으로
적용된다해도, 개발자는 명시적으로 패키지들의 모든 패키지의 리스트를 작성해야한다: Distutils 는 __init__.py 가
있는 어떠한 디렉토리를 찾기 위해서 소스트리를 순환적으로 스캔하지는 않기 때문이다.)&lt;/p&gt;
&lt;p&gt;2.2 Listing individual modules&lt;/p&gt;
&lt;p&gt;작은 모듈을 배포하기 위해서, 개발자는 패키지를 리스팅하기보다는 모든 모듈들을 리스ㄹ팅하기를 선호할 수 있다 (특히
&quot;root package&quot;안의 하나의 모듈만 존재하는 경우). 이러한 간단한 경우는 1.2 장에서 나왔는데 이를 간단히 더
살펴보다면:&lt;/p&gt;
&lt;p&gt;py_modules = [&#039;mod1&#039;, &#039;pkg.mod2&#039;]&lt;/p&gt;
&lt;p&gt;이는 두개의 모듈들을 설명한다. 하나는 &quot;root&quot; 패키지에 존재하고, 다른 하나는 pkg 패키지에 존재한다. 다시
말하자면, 기본 패키지/디렉토리 구조는 이러한 두개의 모듈들이 mod1.py 와 pkg/mod2.py에서 찾을 수 있음을
의미하고, pkg/__init__.py 가 역시 존재할 것임을 의미한다. 그리고 또한 개발자는 package/directory
대응용 package_dir 옵션을 이용해서 오버라이드할 수 있다.&lt;/p&gt;
&lt;p&gt;2.3 Describing extension modules&lt;/p&gt;
&lt;p&gt;2.4 Relationships between Distributions and Packages&lt;/p&gt;
&lt;p&gt;2.5 Installing Scripts&lt;/p&gt;
&lt;p&gt;지금까지 우리는 자신에 의해서 수행되지는 않지만 script들에 의해서 import 되는 pure 와 non-pure Python 모듈들을 다뤄왔다.&lt;/p&gt;
&lt;p&gt;Script들은 커맨드 라인으로부터 실행되도록 의도된 Python source code 를 담고 있는 파일들이다.
Script들은 Distutils이 뭔가 복잡한 일을 하도록 요구하지 않는다. 오직 괜찮은 특징은 만약 스크립트의 첫번째 라인이
#!로 시작하고 python을 담고 있는다면, Distutils는 단지 첫라인을 현재 ㄹ인터프리터의 로케이션을 언급하도록 조정할
뿐이다. 깁ㄴ적으로 이는 현재 인터프리터 위치로 바뀐다. --executable 옵션은 인터프리터 패스가 명시적으로
오버라이드되도록 허용한다.&lt;/p&gt;
&lt;p&gt;scripts 옵션은 간단히 이러한 방법으로 다뤄지는 파일들의 리스트를 보여준다. 예를 들어 PyXML setup script에는 다음처럼 나와있다.&lt;/p&gt;
&lt;p&gt;setup(...&lt;/p&gt;
&lt;p&gt;scripts=[&#039;scripts/xmlproc_parse&#039;, &#039;scripts/xmlproc_val&#039;]&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;2.6 Installing Package Data&lt;/p&gt;
&lt;p&gt;종종 추가적인 파일이 패키지에 설치될 필요가 있다. 이러한 파일들은 종종 패키지들의 구현에 매우 관련된 데이터 혹은
프로그래머가 패키지를 사용함에 있어서 흥미있어할 만한 문서들을 담고 있는 텍스트 파일이기도 하다. 이러한 파일들은 package
data 라 불리운다.&lt;/p&gt;
&lt;p&gt;패키지 데이터는 package 들에 package_data 키워드 아규먼트를 이용해서 setup 함수에 추가된다. 값은
반드시 패키지 이름으로부터 패키지에 카피되어야하는 상대 패스 이름들의 목록으로의 사상이 되어야 한다. 패스들은 패키지를 포함하는
디렉토리 (package_dir 매핑으로부터 나온 정보가 사용되기도 한다.) 에 상대경로써 해석된다; 즉, 파일들은 소스
디렉토리들 내의 패키지의 부분으로 예상된다. 그것들은 glob 패턴들 이용해서 포함될 수 있다.&lt;/p&gt;
&lt;p&gt;패스 이름들은 디렉토리의 일부분들을 포함할 수 있다; 어떤 필요한 디렉토리들은 설치시에 생생된다.&lt;/p&gt;
&lt;p&gt;예를 들어, 만약 패키지가 몇몇 데이터파일들을 갖는 서브디렉토리를 포함해야한다고 한다면, 파일들은 소스트리내에서 다름과 같이 정리될 수 있다:&lt;/p&gt;
&lt;p&gt;setup.py&lt;/p&gt;
&lt;p&gt;src/&lt;/p&gt;
&lt;p&gt;- mypkg/&lt;/p&gt;
&lt;p&gt;- - __init__.py&lt;/p&gt;
&lt;p&gt;- - module.py&lt;/p&gt;
&lt;p&gt;- - data/&lt;/p&gt;
&lt;p&gt;- - - tables.dat&lt;/p&gt;
&lt;p&gt;- - - spoons.dat&lt;/p&gt;
&lt;p&gt;- - - forks.dat&lt;/p&gt;
&lt;p&gt;이에 대응되는 setup() 함수로의 호출은 다음과 같이 될 수 있다.&lt;/p&gt;
&lt;p&gt;setup(...,&lt;/p&gt;
&lt;p&gt;package_dir={&#039;mypkg&#039;: &#039;src/mypkg&#039;},&lt;/p&gt;
&lt;p&gt;package_data={&#039;mypkg&#039;: [&#039;data/*.dat&#039;]},&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;이는 2.4 버전에서부터 추가되었다.&lt;/p&gt;
&lt;p&gt;2.7 Installing Additional Files&lt;/p&gt;
&lt;p&gt;data_files 옵션은 모듈 배포에 필요한 추가적인 파일들 (설정 파일들, 메시지 카탈로그들, 데이터 파일들, 혹은 이전의 카테고리에 속하지 않는 어떠한 파일이든지...)을 열거하는데 사용될 수 있다.&lt;/p&gt;
&lt;p&gt;data_files 는 다음과 같은 방법으로 (directory, files) 쌍의 순서를 열거한다.&lt;/p&gt;
&lt;p&gt;setup(...&lt;/p&gt;
&lt;p&gt;data_files=[(&#039;bitmaps&#039;, [&#039;bm/b1.gif&#039;, &#039;bm/b2.gif&#039;]),&lt;/p&gt;
&lt;p&gt;(&#039;config&#039;, [&#039;cfg/data.cfg&#039;]),&lt;/p&gt;
&lt;p&gt;(&#039;/etc/init.d&#039;, [&#039;init_script&#039;])]&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;눈여겨 봐야할 것은 개발자는 데이터파일들이 설치될 디렉토리의 이름을 열거할 수 있다는 것이다. 그렇지만 데이터파일 자체의 이름을 변경하지는 못한다.&lt;/p&gt;
&lt;p&gt;나열된 각 (directory, files) 쌍은 설치 디렉토리와 그안에 설치될 파일들을 열거한다. 만약 directory
가 상태 패스라면, 설치 프리픽스 (이때 pure_Python 패키지에 대해서는 Python의 sys.prefix,
extension modules 를 포함한 패키지는 sys.exec_prefix)에 대해 상대적으로 해석된다. files 안의
각각의 파일 이름은 패키지 소스 배포판의 최상단에 있는 setup.py script 에 대해서 상대적으로 해석된다. files의
디렉토리 정보는 설치된 파일의 최종 위치를 알아내는데 사용되지 않고, 오직 파일의 이름만이 사용된다.&lt;/p&gt;
&lt;p&gt;개발자는 data_files 옵션들을 대상 디렉토리 없이 파일들의 이름만으로 간단히 열거할 수 있으나, 이러한 방법은
추천하지 않는다. install 커맨드는 이러한 경우에 대해서는 warning 을 프린트할 것이다. 대상 디렉토리에 직접적으로
data files를 설치하려면 디렉토리로서 빈 문자열이 제공되어야 한다.&lt;/p&gt;
&lt;p&gt;2.8 Additional meta-data&lt;/p&gt;
&lt;p&gt;setup script 는 이름, 버전 이되에 추가적인 meta-data 를 포함할 수 있다. 이러한 정보는 다음을 포함한다.&lt;/p&gt;&lt;br /&gt;
&lt;table class=&quot;realtable&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 2px; border-collapse: collapse; empty-cells: show; margin-left: auto; margin-right: auto; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;
  &lt;thead style=&quot;border-width: 0px 0px 2px 1px; background-color: rgb(153, 204, 255); display: table-header-group; font-family: avantgarde,sans-serif; font-weight: bold; vertical-align: baseline;&quot;&gt;
    &lt;tr style=&quot;border-width: 0px 0px 2px;&quot;&gt;
      &lt;th class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 2px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot;&gt;Meta-Data&lt;/th&gt;

      &lt;th class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 2px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;Description&lt;/th&gt;

      &lt;th class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 2px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;Value&lt;/th&gt;

      &lt;th class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 2px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;Notes&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;

  &lt;tbody style=&quot;vertical-align: baseline;&quot;&gt;
    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;name&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;name of the package&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;short string&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;(1)&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;version&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;version of this release&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;short string&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;(1)(2)&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;author&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;package author&#039;s name&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;short string&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;(3)&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;author_email&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;email address of the package author&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;email address&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;(3)&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;maintainer&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;package maintainer&#039;s name&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;short string&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;(3)&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;maintainer_email&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;email address of the package maintainer&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;email address&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;(3)&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;url&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;home page for the package&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;URL&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;(1)&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;description&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;short, summary description of the package&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;short string&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;long_description&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;longer description of the package&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;long string&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;download_url&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;location where the package may be downloaded&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;URL&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;(4)&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em; vertical-align: baseline;&quot; valign=&quot;baseline&quot;&gt;&lt;code style=&quot;font-family: &#039;lucida typewriter&#039;,lucidatypewriter,monospace;&quot;&gt;classifiers&lt;/code&gt;&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;a list of classifiers&lt;/td&gt;

      &lt;td class=&quot;left&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: left; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;list of strings&lt;/td&gt;

      &lt;td class=&quot;center&quot; style=&quot;border-style: solid; border-color: black; border-width: 0px 0px 1px 1px; text-align: center; padding-left: 0.4em; padding-right: 0.4em;&quot;&gt;(4)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;br /&gt;
&lt;p&gt;위 테이블에 대해서&lt;/p&gt;
&lt;p&gt;(1) 이 필드들은 필수적으로 필요하다.&lt;/p&gt;
&lt;p&gt;(2) 이 필드들은 버젼이 major.minor[.patch[.sub]]의 형태를 띨 경우 추천된다.&lt;/p&gt;
&lt;p&gt;(3) author 혹은 maintainer 가 확인되어야만 한다.&lt;/p&gt;
&lt;p&gt;(4) 만약 개발한 패키지가 2.2.3 혹은 2.2.3 앞의 Python version들에 호환된다면, 이 필드들은 사용되지 않는다. 목록은 PyPI 웹사이트에서 찾을 수 있다.&lt;/p&gt;
&lt;p&gt;&#039;short string&#039; 200 글자를 넘지 않는 텍스트의 하나의 라인&lt;/p&gt;
&lt;p&gt;&#039;long string&#039; reStructuredText 포맷을 따르는 plain text 의 다수 라인들&lt;/p&gt;
&lt;p&gt;&#039;list of strings&#039; 아래를 참조&lt;/p&gt;
&lt;p&gt;string 값들이 유니코드가 아닐 수도 있다.&lt;/p&gt;
&lt;p&gt;버전 정보를 인코딩하는 것은 그 나름대로의 규칙이 있다. Python 패키지들은 일반적으로 버전 포맷으로
major.minor[.patch][.sub]를 추가한다. major 번호는 초기, 실험적 릴리즈에 대해서는 0을 사용한다.
그리고 패키지의 주요 마일스톤이 나타날 때, 릴리즈에 대해서 숫자를 올려나간다. minor 숫자는 패키지에 중요한 특징이 추가될
때 증가된다. 패치 번호는 bug-fix 릴리즈가 행해질 때 증가된다. 추가적으로 뒤따라오는 버전 정보는 종종
sub-releases를 나타내기 위해서 사용된다. 이들은 기능성과 API 가 변한 알파릴리즈에 대해서는 &quot;a1, a2,
..., aN&quot;, 버그들만을 수정한 beta 릴리즈에 대해서는 &quot;b1, b2, ... bN&quot;, 그리고 테스팅을 위한
pre-release 릴리즈에 대해서는 &quot;pr1, pr2, ... prN&quot; 이 붙는다.&lt;/p&gt;
&lt;p&gt;2.8 Additional meta-data&lt;/p&gt;
&lt;p&gt;분류자는 다음과 같이 python list 에 의해서 열거된다:&lt;/p&gt;
&lt;p&gt;setup(...&lt;/p&gt;
&lt;p&gt;classifiers=[&lt;/p&gt;
&lt;p&gt;&#039;Development Status :: 4 - Beta&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Environment :: Console&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Environment :: Web Environment&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Intended Audience :: End Users/Desktop&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Intended Audience :: Developers&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Intended Audience :: System Administrators&#039;,&lt;/p&gt;
&lt;p&gt;&#039;License :: OSI Approved :: Python Software Foundation License&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Operating System :: MacOS :: MacOS X&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Operating System :: Microsoft :: Windows&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Operating System :: POSIX&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Programming Language :: Python&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Topic :: Communications :: Email&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Topic :: Office/Business&#039;,&lt;/p&gt;
&lt;p&gt;&#039;Topic :: Software Deveopment :: Bug Tracking&#039;,&lt;/p&gt;
&lt;p&gt;],&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;만약 당신이 setup.py 파일에 분류자를 포함하기를 원한다면, 그리고 역시 Python 2.2.3 이전 버전에 대해서 하위-호환성을 제공하고 싶다면, 당신은 다음 코드 부분을 setup() 호출 이전에 포함해야 한다.&lt;/p&gt;
&lt;p&gt;# patch distutils if it can&#039;t cope with the &quot;classifiers&quot; or&lt;/p&gt;
&lt;p&gt;# &quot;download_url&quot; keywords&lt;/p&gt;
&lt;p&gt;from sys import version&lt;/p&gt;
&lt;p&gt;if version &amp;lt; &#039;2.2.3&#039;:&lt;/p&gt;
&lt;p&gt;from distutils.dist import DistributionMetadata&lt;/p&gt;
&lt;p&gt;DistributionMetadata.classifiers = None&lt;/p&gt;
&lt;p&gt;DistributionMetadata.download_url = None&lt;/p&gt;
&lt;p&gt;2.9 Debugging the setup script&lt;/p&gt;
&lt;p&gt;종종 뭔가 잘못될 수 있는데, 이때 setup script가 개발자가 원하는 것을 해주지는 않는다.&lt;/p&gt;
&lt;p&gt;Distutils 는 setup script 르 수행할 때 예외들을 잡고, script 를 끝내기 전에 간단한 에러
메시지를 프린트한다. 이러한 행동의 모티베이션은 Ptyhon에 대해서 잘 알지 못하는 관리자로 하여금 혼동하지 말고 패키지를
설치를 시도하라는 것을 말한다. 만약 Distutils 가 Distutils 의 깊은 곳으로부터의 기나긴 traceback을
제공한다면 사용자는 아래서부터 읽어서 단순한 퍼미션 문제임을 확인하지 못하고 패키지나 Python 설치가 깨졌다고 생각하게 될
것이다.&lt;/p&gt;
&lt;p&gt;다시 말하자면, 이는 개발자로 하여금 문제의 원인을 찾도록 돕지는 않는다. 이러한 목적으로 위해서
DISTUTILS_DEBUG 환경 변수가 있는데 빈 문자열이 아닌 아무 문자역이 설정되면 distutils 는 무엇을 하는지와
에러가 발생한 경우에 대해서 완전한 traceback을 출력하게 된다.&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;verbatim&quot; style=&quot;margin-left: 2em;&quot;&gt;
  
&lt;/div&gt;</description>
			<category>wkoh+development</category>
			<category>Distribution</category>
			<category>module</category>
			<category>python</category>
			<author>wkoh</author>
			<guid>http://www.v12n.info/19</guid>
			<comments>http://www.v12n.info/19#entry19comment</comments>
			<pubDate>Wed, 07 May 2008 18:09:08 +0900</pubDate>
		</item>
		<item>
			<title>Learning Objective-C: A Primer</title>
			<link>http://www.v12n.info/17</link>
			<description>&lt;p&gt;Objective-C 는 복잡한 객체지향 프로그래밍을 지원하록 설계된 간단한 컴퓨터 언어입니다. Objective-C는 클래스들의 동적 확장을 지원하도록 하는 것 뿐 아니라, 클래스들, 메소드들, 그리고 프로퍼티를 정의하는 신택스를 제공함으로써 표준 ANSI C를 확장하였습니다. 클래스 신택스와 설계는 대부분 최초의 객채지향 프로그래밍 언어 중 하나인 스몰토크에 기반하고 있습니다.&lt;/p&gt;
&lt;p&gt;만약 이전에 개발자가 객체 지향 언어를 이용하여 프로그래밍을 해본 경험이 있다면, 다음 정보들은 Objective-C 의 기본 신택스를 배우는데 도움이 될 것입니다. Encapsulation, inheritance, 그리고 polymorphism 과 같은 많은 전통적인 객체지향 컨셉들은 모두 Objective-C에 나와 있습니다. 하지만 몇가지 중요한 차이점이 있는데, 그 차이점들은 본 문서에도 나와있고 더욱 자세한 정보들도 필요에 따라 구하실 수 있을 것입니다.&lt;/p&gt;
&lt;p&gt;만약 객체지향 언어를 이용해서 프로그래밍해본 경험이 없다면, 적어도 관련된 컨셉들에 대해서 기본적으로 이해해야 할 필요가 있습니다. 객체들의 사용과 객체 지향 구성 개념은 iPhone 응용프로그램의 설계에 필수적이고, 어떻게 그들이 interact하는가를 이해하는 것은 응용프로그램을 작성함에 있어서 매우 중요합니다. 객체 지향 개념에 대해서 오버뷰를 원하신다면, &lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/OOP_ObjC/index.html&quot;&gt;Object-Oriented Programming with Objective-C&lt;/a&gt; 문서를 보시기 바랍니다.&lt;/p&gt;
&lt;p&gt;Objective-C 언어와 신택스에 대한 더욱 자세한 소개를 원하시면 &lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/index.html&quot;&gt;Objective-C 2.0 Programming Language&lt;/a&gt; 를 보시기 바랍니다.&lt;/p&gt;&lt;p id=&quot;more17_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;17_0&#039;,&#039; more.. &#039;,&#039; less.. &#039;); return false;&quot;&gt; more.. &lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content17_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt; &lt;p&gt;&lt;strong&gt;Objective-C: A Superset of C&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Objective-C는 C 프로그래밍 언어의 ANSI 버전의 superset이고 C와 동일한 기본 신택스를 지원합니다. C
code를 이용하는 것과 마찬가지로 개발하는 코드의 구현에서 퍼블릭 선언들을 분리하기 위해서 header 파일들과 source
파일들을 정의하게 됩니다. Objective-C header 파일들은 표 1에서 보이는 바와 같은 file 확장자를 사용합니다.&lt;/p&gt;&lt;br /&gt;
&lt;table id=&quot;demo-table&quot;&gt;
  &lt;caption&gt;
    표 1. Objective-C 코드의 파일 확장자
  &lt;/caption&gt;

  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;확장자&lt;/th&gt;

      &lt;th&gt;소스타입&lt;/th&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th&gt;.h&lt;/th&gt;

      &lt;td&gt;Header 파일들. Header 파일들은 class, type, function그리고 상수 선언을 담고 있다.&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th&gt;.m&lt;/th&gt;

      &lt;td&gt;Source 파일들. 이는 소스파일들에서 사용되는 기본적인 확장으로써 Objective-C 와 C 코드 양측에서 사용이 가능하다.&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;th&gt;.mm&lt;/th&gt;

      &lt;td&gt;Source
파일들. 이 확장자를 갖는 소스파일은 Objective-C 와 C 코드에 추가적으로 C++ 코드를 포함할 수 있다. 이 확장은
개발하는 Objective-C 코드에서 C++ 클래스 혹은 기능을 사용하고자 할 때만 사용해야 한다.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;br /&gt;
&lt;p&gt;개발자가 소스코드에서 header 파일들을 include 하려고 할 때, 개발자는 표준 #include 컴파일러 디렉티브
(directive)를 사용할 수 있지만, Objective-C 에서는 더 나은 방법을 제공하고 있다. #import 디렉티브는
같은 파일은 두번 이상 포함되지 않도록 하는 부분을 추가적으로 제공하는 부분을 제외하고는 #include 와 동일하다.
Objective-C 샘플들과 문서들 모두 #import 를 사용하기를 선호하고, 개발자가 개발하려는 코드 역시 그래야한 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Strings&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;C의 superset으로써, Objective-C는 C 처럼 스트링을 사용함에 있어서 동일한 컨센션들을 지원합니다. 다시
말하자면, 하나의 문자들은 작은 따옴표로 묶고, 문자들의 스트링은 따옴표로 묶습니다. 그러나, 대부분의 Objective-C
프레임워크들은 C 스타일의 스트링을 거의 사용하지 않습니다. 대신 대부분의 프레임워크들은 NSString 객체를 이용하게 됩니다.&lt;/p&gt;
&lt;p&gt;NSString 클래스는 임의의 길이를 가진 스트링을 저장하기 위한 내장된 메모리 관리, 유니코드 지원, printf
스타일의 포맷팅 유틸리티, 그리고 그 이상의 예상할 수 있는 모든 장점을 갖고 있는 스트링을 위한 객체 래퍼 (wrapper)를
제공합니다. 역시 이러한 스트링들이 공용적으로 사용되기 때문에, Objective-C는 상수값으로부터 NSString 객체를
만들기 위한 짧은 노테이션을 제공합니다. 이러한 shorthand 를 사용하기 위해서, 개발자가 해야하는 것은 다음 예제에서
보이는 것과 같이 @ 심볼을 따옴표를 이용한 일반적인 스트링의 앞에 위치시키는 것입니다.&lt;/p&gt;&lt;br /&gt;
&lt;table id=&quot;demo-table&quot;&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;NSString* myString =@&quot;My String\n&quot;;&lt;br /&gt;
      NSString* anotherString = [NSString stringWithFormat:@&quot;%d %s&quot;, 1, @&quot;String&quot;];&lt;br /&gt;
      &lt;br /&gt;
      // Create an Objective-C string from a C string&lt;br /&gt;
      NSString* fromCString = [NSString stringWithCString:&quot;A C string&quot; encoding:NSASCIIStringEncoding];&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;Classes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;대부분의 다른 객체지향 언어에서와 마찬가지로, Objective-C 는 일부 데이터와 그 데이터를 이용해 동작하는 액션들을
encapsulate한 기본 Construct 를 제공합니다. 객체는 간단히 말해서 클래스의 동적인 인스턴스이고, 클래스에
의해서 선언된 멤버 변수의 in-memory 카피를 가지고 클래스의 메소드에 대한 포인터를 갖고 있습니다.&lt;/p&gt;
&lt;p&gt;Objective-C에서 클래스의 specification은 두개의 별개의 부분을 필요로 하는데, 이는 인터페이스와
임플리먼테이션입니다. 인터페이스 부분은 클래스 정의와 멤버 변수와 해당 클래스에 관련된 메소드들의 정의를 포함합니다.
임플리먼테이션 부부은 클래스의 메소드들을 위한 실제 코드를 담고 있습니다. 그림 1은 MyClass라 불리오는 클래스를 정의하는
신택스를 보여줍니다. 이는 NSObject 베이스클래스로부터 상속을 받은 클래스입니다. 클래스 선언은 언제나 @interface
컴파일러 디렉티브로 시작하고 @end 디렉티브로 끝납니다. 다음으로는 클래스 이름과 부모 클레스의 이름이 나옵니다. 클래스의
멤버 변수들은 중괄호에 의해서 제한된 코드 블럭 내에서 선언됩니다. 다음으로 나오는 멤버 변수 들럭은 클래스에 의해서 선언되는
메소드들의 목록입니다. 세미콜론 문자는 각 멤버 변수와 베소드 선언의 끝을 나타닙니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  그림 1. 클래스 선언&lt;br /&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;http://cfs6.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNi50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTcwMDAwMDAwMDAxLmpwZw==&quot; width=&quot;480&quot; height=&quot;199&quot; /&gt;&lt;br /&gt;
  &lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;그림 2는 앞서 나온 예제인 MyClass 의 임플리먼테이션을 보여줍니다. 클래스 선언과 동일하게, 클래스 구현은 두개의
컴파일러 디렉티브들 (@implementation 과 @end)로 확인됩니다. 이러한 디렉티브들은 컴퍼일러가 연관된 클래스와
메소드들을 연관짓는데 필요한 scoping 정보를 제공하게 됩니다. 그러므로, 하나의 메소드의 정의는, 코드블록에서 포함된 것을
제외하고는, 인터페이스에서 연관된 정의와 동일해야 합니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  그림 2. 클래스 임플리먼테이션&lt;br /&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;http://cfs5.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTcwMDAwMDAwMDAyLmpwZw==&quot; width=&quot;480&quot; height=&quot;308&quot; /&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;다음 예제는 MyClass 클래스를 위한 String typing과 weak typing 변수 선언을 보여줍니다.&lt;/p&gt;&lt;br /&gt;
&lt;table id=&quot;demo-table&quot;&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;MyClass* myObject1; // String typing&lt;br /&gt;
      id myObject2; // Weak typing&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;Methods&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Objective-C에서 클래스는 두 종류의 메소드들 (인스턴스 메소드들과 클래스 메소스들)을 선언할 수 있습니다.
인스턴스 메소드는 그 수행이 클래스의 해당 인스턴스에 한정되는 메소드입니다. 다시 말하자면, 인스턴스 메소드를 호출하기 전에,
먼저 클래스의 인스턴스를 생성해야만 하고, 그런 후 실제 그 인스턴스가 해당 메소드를 로출하게 됩니다. 비교하자면 클래스
매소드는 인스턴스를 생성할 필요가 없으며, 필요하다면 후에 생성해도 됩니다.&lt;/p&gt;
&lt;p&gt;메소드의 선언은 메소드 타입 아이던티파이어 (identifier), 리턴 타입, 하나 혹은 그이상의 signature
카워드들, 그리고 파라메터 타입과 이름 정보 들로 구성됩니다. 그림 3은 insertObject:atIndext: 인스턴스
메소드의 선언을 보여준다. 선언은 마이너스 (-) 사인으로 시작하는데 이는 해당 메소드가 인스턴스 메소드임을 나타낸다. 메소드의
실제 이름 (insertObject:atIndex:)는 콜론 문자를 포함해서 모든 시그니쳐의 연결입니다. 콜론 문자는 파라메터가
있음을 선언합니다. 만약 메소드가 파라메터가 없었다면 첫 시그니쳐 키워드 뒤의 콜론을 생략할 수 있습니다. 이 예제에서는
메소드는 두개의 파라메터를 갖습니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  그림 3. 메소드 선언 신택스&lt;br /&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;http://cfs4.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNC50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTcwMDAwMDAwMDAwLmpwZw==&quot; width=&quot;480&quot; height=&quot;217&quot; /&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;개발자가 메소드를 호출할 때, 개발자는 연관된 객체에 &quot;메세징&quot;을 통해서 그렇게 할 수 있습니다. 이러한 경우에서 메세지는
메소드가 필요로하는 파라메서 정보와 함께, 메소드 시그니쳐가 됩니다. 당신이 객체에 보내느 모든 메시지는 동적으로 디스패치되고,
그럼으로써 Objective-C 클래스들의 polymorphism behavior 를 용이하게 합니다. 다시 말해서,
자식클래스가 부모 클래스의 하나와 같은 시그니쳐를 갖는 메소드를 정의했다면, 자식클래스는 메시지를 먼저 받고 메시지를 부모에게
전달하지 말지를 선택할 수 있습니다.&lt;/p&gt;
&lt;p&gt;메시지들은 대괄호([, ])로 싸여습니다. 대괄호 안에서 메시지를 받은 객체는 왼편에 있고 (메시지에 필요로하는 어떠한
파라메터와 함께) 메시지는 오른편에 있게 됩니다. 예를 들어, insertObject:atIndex: 메세지를 myArray
변수에 있는 객체에게 보내려고 한다면, 다음과 같은 신택스를 사용할 수 있습니다.&lt;/p&gt;&lt;br /&gt;
&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;[myArray insertObject:anObj atIndex:0];&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;임시 결과를 저장하기 위한 무수한 로컬 변수를 선언하는 것을 피하기 위해서, Objective-C는 개발자가 메시지들을
네스트하도록 허용합니다. 각각의 네스트된 메시지들로 부터의 리턴값은, 다른 메시지의 파라메터 혹은 타겟으로 쓰일 수 있습니다.
예를 들어, 당신이 값을 찾아오도록 하는 메시지를 이용해서 이전 예제에서 사용된 어떤 변수들을 대체하려 할 수 있다. 그렇다면
만약 array 객체에 접근하여 해당 객체를 array 에 삽입하는 myAppObject 라 불리오는 또하나의 객체를 가지고
있다면, 당신은 이전 예제를 다음과 같이 보이게 작성할 수 있습니다.&lt;/p&gt;&lt;br /&gt;
&lt;table id=&quot;demo-table&quot;&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;[[myAppObject getArray] insertObject:[myAppObject getObjectToInsert] at Index:0];&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;앞선 예제가 메시지를 클래스의 인스턴스에 보낸 것에 반해 당신은 역시 메시지를 클래스 자체에 보낼 수 있습니다. 클래스에
메세지를 보낼 때, 명시한 메소드는 인스턴스 메소드 대신에 클래스 메소드로서 정의되었어야합니다. 당신은 클래스 메소드들을
정확하게는 아니지만 C++ 클래스에서 스태틱 멤버들과 유사하게 생각할 수 있습니다.&lt;/p&gt;
&lt;p&gt;당신은 기본적으로 클래스로부터 새로운 인스턴스를 만들어내는 혹은 그 클래스에 연관된 공유된 정보의 일부를 접근하는 팩토리
메소드들과 같은 클래스 메소드를 사용합니다. 클래스 메소드의 선언을 위한 신택스는 인스턴스 메소드를 만드는 것과 한가지 예외를
제외하고는 동일합니다. 메소드 타입 아이던테파이어에서 마이너스 사인 대신에 플러스 (+) 사인을 사용하게 됩니다.&lt;/p&gt;
&lt;p&gt;다음 예는 클래스를 위한 팩토리 메소드로서 클래스 메소드를 사용하는 것을 보여줍니다. 이러한 경우에
arrayWithCapacity: 메소드는 클래스의 새로운 인스턴스를 할당, 초기화하고 그것을 코드로 반환하는
NSMutableArray 클래스 상의 클래스 메소드입니다.&lt;/p&gt;&lt;br /&gt;
&lt;table id=&quot;demo-table&quot;&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;NSMutableArray* myArray = nul; // nul 은 기본적으로 NULL 과 같습니다.&lt;br /&gt;
      &lt;br /&gt;
      // 새로운 배열을 만들고 이를 myArray 변수에 할당합니다.&lt;br /&gt;
      myArray = [NSMutableArray arrayWithCapacity;0];&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Properties&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;프로퍼티들은 접근자 (accessor) 메소드들을 대채하는데 사용되는 편의 노테이션입니다. 프로터티들은 작성하는 클래스
정의에서 새로운 멤버 변수들을 생성하지 않습니다. 프로퍼티들은 단순히 이미 존재하는 멤버 변수들을 접근하는 메소드들을 정의하는
데 사용되는 shorthand입니다. 멤버 변수들을 표출하는 클래스들은 getter 그리고 setter 메소드들을 이용하는
대신에 프로퍼티 노테이션을 이용하여 그렇게 할 수 있습니다. 클래스들은 역시 &quot;가상&quot; 멤버 변수들 (즉, 동적으로 계상되는
데이터와 실제로는 멤버 변수들에 저장되지 않는 데이터들의 조각) 을 표출하는데 프로퍼티들을 사용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;실전적으로 마하자면, 프로퍼티들은 작성해야 하는 중복된 코드의 양을 줄입니다. 대부분의 접근자 메소드들은 공일한 방법으로
구현되지 때문에, 프로퍼티들은 클래스에서 포출하는 각각의 멤버 변수들에 대한 별개의 getter와 setter를 제공할 필요를
제거합니다. 대신 개발자는 프포퍼티 선언을 이용해서 원하는 behavior 를 명시해야하고, 그런 후 컴파일 타임에 해당 선언에
기반을 둔 실제 getter 와 setter 메소드들을 종합적으로 다루게 됩니다.&lt;/p&gt;
&lt;p&gt;프로퍼티 선언들이 실제 메소드들을 생성하는 결과를 낳기 때문에, 개발자는 작성하는 클래스 인터페이스에서 메소드 선언와 함께
그들을 포함하게 됩니다. 기본 정의는 @property 컴파일러 디렉티브를 사용하고, 이의 뒤에 프로퍼티의 타입 정보와 이름이
뒤따르게 됩니다. 개발자는 역시 사용자 옵션을 가지고 프로퍼티를 설정할 수 있고, 이는 접근자 메소드들이 어떻게 행위하는지를
정의합니다. 다음 예제는 몇개의 간단한 프로퍼티 선언들을 보여줍니다.&lt;/p&gt;&lt;br /&gt;
&lt;table id=&quot;demo-table&quot;&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;@property BOOL flag;&lt;br /&gt;
      @property (copy) NSString* nameObject; //할당하는 동안 객체를 복사&lt;br /&gt;
      @property (readonly) UIView* rootView; // getter 메소드만을 생성&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;프로퍼티들의 또다른 장점은 다음 예제에서 보이는 바와 같이 개발하는 코드에서 그들을 접근할 때, 마침표 (.) 신택스를 사용할 수 있다는 점입니다.&lt;/p&gt;&lt;br /&gt;
&lt;table id=&quot;demo-table&quot;&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;myObject.flag = YES;&lt;br /&gt;
      CGRect viewFrame = myObject.rootView.frame;&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;앞선 예제들에서 객체와 프로퍼티의 이름들이 꾸며낸 것임에도 불구하고, 이는 프로퍼티들의 유연성을 보여줍니다. 마침표
신택스는 실제로 메소드 호출들의 연관된 셋을 실제로 가려줍니다. 각각의 읽을 수 있는 프로퍼티는 프로퍼티와 같은 이름을 갖는
메소드들에 의해서 구현됩니다. 각각의 쓰기가능한 프로퍼티는 프로퍼티 이름의 첫번째 문제가 대문자로 시작하는
setPropertyName: 형식의 추가적인 메소드에 의해서 구현됩니다. (이러한 메소드들은 프로퍼티들의 실제 구현들이고
개발자가 멤버 변수들에 의해서 구현되지 않는 클래스들의 속성들을 위한 프로퍼티 정의를 포함할 수 있는 이유가 됩니다.) 앞선
예제 코드를 프로퍼티 대신 메소드를 이용해서 구현한다면 다음 코드와 같이 작성해야 합니다.&lt;/p&gt;&lt;br /&gt;
&lt;table id=&quot;demo-table&quot;&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;[myObject setFlag:YES];&lt;br /&gt;
      CGRect viewFram = [[myObject rootView] frame];&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;개발자 자신의 클래스에서 프로퍼티들을 어떻게 선언하는지를 알고싶다면, &lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/index.html&quot;&gt;The Objective-C 2.0 Programming Language&lt;/a&gt;의 &quot;&lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_5_section_1.html&quot;&gt;Properties&lt;/a&gt;&quot;를 읽어보시기 바랍니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Protocols and Delegates&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;프로토콜은 어떠한 클래스에서든지 구현될 수 있는 메소드들을 정의합니다. 프로토콜들은 클래스 자체는 아닙니다. 프로토콜들은
단순히 다른 객체들이 구현해야하는 책임을 갖는 인터페이스를 정의합니다. 개발자가 클래스들의 하나에서 하나의 프로토콜의 메소드를
구현할 때, 개발자의 클래스는 그러한 프로토콜을 만족하기위해서 언급됩니다.&lt;/p&gt;
&lt;p&gt;iPhone OS에서 프로토콜은 delegate 객체들을 구현할 때 자주 사용됩니다. delegate 객체는 또 다른
객채와 함께, 혹은 또 다른 객체를 위해서 동작하는 객체입니다. 프로토콜간의 상호작용을 찾기 위한 최고의 방법은
delegate들과 다른 객채들을 예제에서 살펴보는 것입니다.&lt;/p&gt;
&lt;p&gt;UIApplication 클래스는 응용프로그램에서 필요로하는 behavior 를 구현합니다. 개발자가 자식클래스
UIApplication 이 응용프로그램의 현재 상태에 대해서 간단한 알림들을 받도록 강제하는 대신에, UIApplication
클래스는 그러한 알림들을 자신에게 할당된 delegate 객체의 특정 메소드들을 호출함으로써 전달합니다.
UIApplicationDelegate 프로토콜의 메소드들을 구현하는 객체는 이러한 알림들을 받을 수 있고 적절한 응답을
제공합니다.&lt;/p&gt;
&lt;p&gt;프로토콜의 선언은 클래스 인터페이스와 매우 비슷하게 보입니다. 하지만 프로토콜은 부모 클래스를 가지고 있지 않고, 멤버
변수들을 정의하지 않는 다는 점이 차이점입니다. 다음 예제는 하나의 메소드를 갖는 간단한 프로토콜 선언을 보여줍니다.&lt;/p&gt;&lt;br /&gt;
&lt;table id=&quot;demo-table&quot;&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;@protocol MyProtocol&lt;br /&gt;
      - (void)myProtocolMethod;&lt;br /&gt;
      @end&lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;많은 delegate 프로토콜들의 경우, 프로토콜을 사용하는 것이 간단하게는 해당 프로토콜에 의해 정의된 메소드들을 구현에
관한 문제이다. 개발자가 명시적으로 프로토콜을 지원한다고 언급할 필요가 있는 일부 프로토콜이 있기는 하지만, 현재로서는 개발자는
메소드들을 구현하는 것으로도 충분하다고 여길 수 있습니다. 그러나, 개발자가 더욱 개발을 진행함에 따라서 프로토콜에 대해서
배우는데 좀더 많은 시간을 보내야 하며, 이는 &lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/index.html&quot;&gt;The Objective-C 2.0 Programming Language&lt;/a&gt;의 &quot;&lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_6_section_1.html&quot;&gt;Protocols&lt;/a&gt;&quot;를 읽어볼 필요가 있다는 것을 뜻합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For More Information&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;앞서 언급된 정보들은 기본적으로 개발자가 Objective-C 언어의 기본에 익숙해지도록 의도하고 있습니다. 여기서 다른
주제는 개발자가 문서의 나머지를 읽어감에 따라 겪게 될 대부분의 언어 특징을 반영하는 것이었습니다. 이는 단지 언어 전반에 대한
특징이 아니기 때문에 &lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/index.html&quot;&gt;The Objective-C 2.0 Programming Language&lt;/a&gt;에서 언어에 대해서 좀더 읽어보기를 장려합니다.&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;</description>
			<category>wkoh+apple</category>
			<author>wkoh</author>
			<guid>http://www.v12n.info/17</guid>
			<comments>http://www.v12n.info/17#entry17comment</comments>
			<pubDate>Thu, 13 Mar 2008 11:19:27 +0900</pubDate>
		</item>
		<item>
			<title>Tools for iPhone OS Development</title>
			<link>http://www.v12n.info/16</link>
			<description>&lt;p&gt;iPhone OS 를 위한 응용프로그램을 개발하기 위해서는, Xcode 툴을 수행하는 Mac OS X 컴퓨터가 필요합니다. Xcode 는 애플의 개발 도구 Suite 로써 프로젝트 관리, 코드 수정, 실행환경의 빌딩, 소스 수준의 디버깅, 소스코드 저장소 관리, 성능 튜닝, 그리고 다수의 기능을 제공합니다. 이러한 Suite의 중앙에는 Xcode 응용프로그램이 존재하는데, 기본 소스 코드 개발 환경을 지원하게 됩니다, Xcode 는 개발자가 사용하는 도구로서만이 아니라 iPhone 응용프로그램을 작성하는데 사용할 수 있는 응용프로그램에 대한 소개를 제공하는 다음 섹션까지 포함합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Xcode&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;개발자의 개발 경험의 중심에는 Xcode 응용프로그램이 있습니다. Xcode 는 당신의 iPhone 프로젝트와 소스 파일들을 생성과 관리, 당신의 코드를 실행환경으로 빌드, 그리고 iPhone 시뮬레이터 혹은 디바이스 상에서 코드의 수행과 디버그하는데 필요로하는 도구들 전부를 제공하는 통합 개발 환경 (IDE)입니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  그림 1. Xcode 프로젝트 윈도&lt;br /&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;http://cfs6.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNi50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTcwMDAwMDAwMDAwLmpwZw==&quot; width=&quot;480&quot; height=&quot;250&quot; /&gt;&lt;br /&gt;
  &lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;새로운 iPhone 응용프로그램을 만들기 위해서는 Xcode 상에서 새로운 프로젝트를 생성함으로써 시작합니다. 하나의 프로젝트는 당신의 응용프로그램에 관련된 모든 정보 (소스파일들, 빌드 설정, 그리고 모든 부분들을 함께 담는데 필요로하는 룰)를 관리합니다. 모든 Xcode 프로젝트의 심장은 그림 1에서 보이는 프로젝트 윈도입니다. 이 윈도는 작성하는 응용프로그램의 모든 중요한 요소들에 대한 빠른 접근을 제공합니다. 그룹들과 파일들 목록은 소스파일들과 이러한 소스파일들로부터 생성되는 빌드 타겟을 포함하는, 작성하는 프로젝트의 파일들을 관리하는 곳입니다. 툴바는 공통적으로 사용되는 툴과 커맨드에 대한 접근을 제공하는 반면 자세한 부분은 프로젝트상에서 동작하기 위한 설정가능한 스페이스로서 제공됩니다. 프로젝트 윈도의 다른 부분은 프로젝트에 대한 컨텍스트 인포메이션으로 제공됩니다.&lt;/p&gt;&lt;p id=&quot;more16_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;16_0&#039;,&#039; more.. &#039;,&#039; less.. &#039;); return false;&quot;&gt; more.. &lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content16_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt; &lt;p&gt;Xcode는 진보한 텍스트 에디터를 포함하는데 이는 코드 컴플리션, 신텍스 컬러링, 코드 폴딩 (코드블럭을 임시적으로
숨기는), 에러에 대한 인라인 어노테이션 그리고 노트들 과 같은 특징들을 지원합니다. Xcode 내의 빌드 시스템은 적절한 기본
설정과 개발자의 입맛에 맞추도록 환경을 설정할 수 있는 기능 모두를 제공합니다. 그리고 만약 문서가 필요하다면, Research
Assistant는 Xcode 문서 윈도를 통해서 정보를 브라우즈하고 찾을 수 있도록 제공합니다.&lt;/p&gt;
&lt;p&gt;개발자가 Xcode 를 이용하여 응용프로그램을 빌드할 때, 개발자는 iPhone을 이용할지 하니면 디바이스를 이용할지를
선택하게 됩니다. 시뮬레이터는 응용프로그램을 테스트하여 원하는 바대로 개발한 응용프로그램이 동작하는지를 테스트하는 로컬환경을
제공합니다. 갭라한 응용프로그램의 기본적인 비헤비어에 만족스러웠다면, 그다음 Xcode를 이용하여 빌드하고 컴퓨터에 연결된
iPhone 혹은 iPod touch 상에서 이를 수행시켜 보십시요. 디바이스 상에서 운영하는 것은 궁극적인 테스트 환경을
제공하고, Xcode 는 디바이스 상에서 동작하는 코드에 내장된 디버서를 접합시키도록 허용합니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  그림 2. Xcode 로부터의 프로젝트의 수행&lt;br /&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;http://cfs5.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTcwMDAwMDAwMDAwLmpwZw==&quot; width=&quot;480&quot; height=&quot;380&quot; /&gt;&lt;br /&gt;
  &lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;어떻게 iPhone OS 상에서 개발한 프로젝트를 빌드하고 동작하는지에 대한 자세한 것은 &lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/index.html&quot;&gt;iPhone OS Programming Guide&lt;/a&gt; 의 &quot;&lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/DevelopmentEnvironmentOverview/chapter_4_section_1.html&quot;&gt;Development Environment&lt;/a&gt;&quot; 를 참조하시기 바랍니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Interface Builder&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;인터페이스 빌더는 개발하는 응용프로그램의 사용자 인터페이스를 시각적으로 조합하는데 사용할 수 있는 툴입니다. 인터페이스
빌드를 이용해서, 이미 설정되어있는 컴포넌트를 응용프로그램의 윈도로 드래그 &amp;amp; 드롭함으로써 응용프로그램의 윈도를 조합할
수 있습니다. 컴포넌트들은 스위치, 텍스트 필드, 그리고 버튼들과 같은 표준화된 시스템 컨트롤들을 포함하고, 역시 개발하는
응용프로그램이 제공하는 뷰를 나타내는 커스텀 뷰를 포함합니다. 개발자는 컴포넌트를 윈도의 화면에 위치시킨 후, 컴포넌트를
드래그함으로써 위치시킬 수 있고, 인스펙터를 이용해서 속성을 설정할수 있으며, 코드와 이러한 오브젝트들간의 관계를 설정할 수
있습니다. 개발자의 인터페이스가 원하는 대로 보이게 되면, 사용자 자원 파일 포맷인 nib 파일로 컨텐츠를 저장하게 됩니다.&lt;/p&gt;
&lt;p&gt;인터페이스 빌더를 통해서 생성한 nib 파일들은 UI Kit 에서 런타임에 작성한 응용프로그램의서 같은 오프벡트들을
재생성하는데 필요한 정보 모두를 포함하고 있습니다. nib 파일을 로딩하는 것은 파일에 저장되어 있는 모든 오브젝트들의 런타임
버전을 생성하고, 인터페이스 빌드에서 만들어진 것과 정확히 동일하게 스 설정을 하게 됩니다. 이는 역시 새로이 만들어진
오브젝트들과 개발한 응용프로그램에서 기본에 존재해왔던 어떠한 오브젝트들 같의 연결을 설정하기 위해서 정의한 연결 정보를 이용하게
됩니다. 이러한 연결들은 개발한 코드에게 nib 파일 오브젝트들로의 포인터를 제공하고, 역시 개발한 코드에 사용자 액션들과
통신하는데 필요로하는 오브젝트 자체에 대한 정보를 제공하게 됩니다.&lt;/p&gt;
&lt;p&gt;전반적으로, 인터페이스 빌더를 사용하는 것은 응용프로그램의 사용자 인터페이스를 작성할때 발생하는 많은 시간을 절약하게
해줍니다. 인터페이스 빌더는 인터페이스를 구성하는 오브젝트들의 생성, 설정, 포지션에 필요로하는 사용자 코드를 제거합니다. 이는
비쥬얼 에디터이게 때문에, 정확하게 사용자의 인터페이스가 런타임에 보이는 것과 동일하게 보여지게 됩니다.&lt;/p&gt;
&lt;p&gt;Note: 인터페이스 빌더는 iPhone SDK의 초기 베타버젼에는 포함되지 않습니다. 이는 해당 프로덕트의 최종 릴리즈에 포함될 예정입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Instruments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;당신이 개발한 소프트웨어를 위한 최상의 사용자 경험을 가져다 주도록 확신토록 하기 위해, Instruments 환경은
개발자가 시뮬레이터 혹은 디바이스 상에서 개발한 iPhone 응용프로그램이 돌아갈 때의 성능을 분석하도록 해줍니다.
Instruments는 개발자의 동작하는 응용프로그램으로 부터 데이터를 얻고 Timeline이라 불리우는 그래픽 디스플레이에
데이터를 표현해 줍니다. 개발자는 개발한 응용프로그램의 메모리 사용, 디스크 동작, 네트워크 활동, 그리고 그래픽 성능에 관한
데이터를 수집할 수 있습니다. Timeline 뷰는 모든 다른 종류의 정보들을 차례대로 표시하는데, 이는 개발한 응용프로그램의
단지 하나에 제한적인 부분에 대한 behavior 만이 아닌, 전반적인 behavior들를 관련시킬 수 있도록 허용합니다. 더욱
자세한 정보를 원하면, Instruments 가 취합한 보다 자세한 샘플들을 볼 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  그림 3. Instuments 를 이용하여 개발하는 응용프로그램을 튜닝&lt;br /&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;http://cfs5.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTcwMDAwMDAwMDAxLmpwZw==&quot; width=&quot;480&quot; height=&quot;370&quot; /&gt;&lt;br /&gt;
  &lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;Timeline 뷰를 제공하는 것에 추가적으로 Instruments 는 시간에 따라 개발한 응용프로그램의 behavior
를 분석하는 것을 도와주는 도구를 제공합니다. 예를 들어, Instruments 윈도는 복수 수행으로부터 데이터를 저장하도록
제공하고, 그럼으로써 개발하고 있는 응용프로그램의 behavior가 실제로 향상되고 있는지 혹은 아직 일을 더 해야할지를 볼 수
있습니다. 개발자는 Instuments 문서에 이러한 수행으로부터 얻은 데이터를 저장할 수 있고 언제든지 그것을 열람할 수 있게
됩니다.&lt;/p&gt;
&lt;p&gt;어떻게 iPhone 응용프로그램을 가지고 Instruments 를 사용하는지에 대한 자세한 사항은 &lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/index.html&quot;&gt;iPhone OS Programming Guide&lt;/a&gt; 의 &lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/DevelopmentEnvironmentOverview/chapter_4_section_1.html&quot;&gt;Development Environment&lt;/a&gt; 를 참조하시기 바랍니다. 어떻게 Instruments 를 사용하는지에 대한 일반적인 정보는 &lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/index.html&quot;&gt;Instruments User Guide&lt;/a&gt; 에 있습니다.&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;</description>
			<category>wkoh+apple</category>
			<author>wkoh</author>
			<guid>http://www.v12n.info/16</guid>
			<comments>http://www.v12n.info/16#entry16comment</comments>
			<pubDate>Wed, 12 Mar 2008 18:29:20 +0900</pubDate>
		</item>
		<item>
			<title>CentOS 5.1 on intel DQ35JO</title>
			<link>http://www.v12n.info/15</link>
			<description>&lt;p&gt;그간 intel의 VT-d에 관심이 있었어서 VT-D가 가능한 환경을 만들려고 서베이를 좀 했다.&lt;br /&gt;
그러던 중에&lt;br /&gt;
&lt;a href=&quot;http://wiki.xensource.com/xenwiki/VTdHowTo&quot;&gt;http://wiki.xensource.com/xenwiki/VTdHowTo&lt;/a&gt;&lt;br /&gt;
에서 VT-d 가 가능한 환경을 찾았는데. xensource 에서 개발환경으로 사용되는 intel 의 마더보드가&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;DQ35MP&lt;/li&gt;

  &lt;li&gt;DQ35JO&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;라는 사실을 알게 되었다. 물론 몇가지 더 지원하는 시스템이 있을 것이고, Q35 칩셋을 이용하는 마더보드에서는 지원할 것이라는 어렴풋한 추측이 있기는 하지만.. 괜히 무턱대고 구입했다가 BIOS에서 이를 enable시키지 못해서 ACPI table 에서 찾지 못하게 되면.. 괜히 낭패가 될 것같아서.. 안전빵으로 갔다. (그리고 개인적으로, 옛날과는 다르게, 오버라든지 다른 메인보드의 특별한 기능을 찾을만큼 정열적이진 않아서... 돌다리도 두들겨가는 심정으로.. ^.^)&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;그림 1. BIOS of DQ35JO&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;http://cfs5.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTUwMDAwMDAwMDAwLmpwZw==&quot; width=&quot;220&quot; height=&quot;176&quot; alt=&quot;080307-0001.jpg&quot; /&gt;&lt;br /&gt;
&lt;/div&gt;일단 DQ35JO 메인보드를 구입했고... 책상위에 올려놓고 대충 뚝딱뚝딱 있는 부품들을 모아서 조립했다. 메모리같이 없었던 것은 선배한테 빌려서.. ㅡ.ㅡ. 아무튼 그림과 같이 해당 메인보드의 BIOS 에서

&lt;ul&gt;
  &lt;li&gt;VT Technology&lt;/li&gt;

  &lt;li&gt;Intel(R) VT for Directed I/O (VT-d)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;가 존재함을 확인했다. (사실 인터넷에서 DQ35JO의 BIOS에서 정말로 VT-d에 관한 enable이 가능한지를 찾을 수 가 없어서 답답했는데... 있어서 다행이었다.)&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;그리고 현재는 CentOS 5.1 를 하고 있는 중이다. 하지만 설치시 그냥 설치가 되지는 않는데... 설치시에만 pci=nommconf 옵션을 주고 설치해야 한다. 지금은 일단 설치중&lt;/p&gt;</description>
			<category>wkoh+virtualization</category>
			<author>wkoh</author>
			<guid>http://www.v12n.info/15</guid>
			<comments>http://www.v12n.info/15#entry15comment</comments>
			<pubDate>Fri, 07 Mar 2008 17:31:42 +0900</pubDate>
		</item>
		<item>
			<title>iPhone OS Overview</title>
			<link>http://www.v12n.info/14</link>
			<description>&lt;p&gt;애플에서 2008년 3월 6일 iphone 에 관련된 software roadmap에 대해서 발표했다.&lt;/p&gt;
&lt;p&gt;이와 동시에 개발자를 위한 SDK의 발표과 개발관련 자료를 배포했는데, iPhone OS 에 관련된 overview 가 있어서 이렇게 올려놓는다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;iPhone OS Overview&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;iPhone OS 는 운영체제와 iPhone 과 iPod touch 디바이스에서 네이티브하게 응용프로그램들을 동작하게 하는 기술들을 포함합니다. 이는 공통된 전통(?)과 mac os x 와 많은 하부 기술들을 공유함하지만, iPhone OS 는 사용자의 요구가 분명히 다른, 모바일 환경의 요구를 충족하도록 설계되었습니다. 존재하는 Mac OS X 개발자들은 많은 친근한 기술들을 착을 수 있지만, 그들 역시 오직 iPhone OS 에서만 가능한 Multi-touch 인터페이스, 가속도계 (accelerometer) 지원등의 기술도 찾을 수 있을 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://cfs6.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNi50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTUwMDAwMDAwMDAyLmpwZw==&quot; width=&quot;457&quot; height=&quot;369&quot; /&gt;&lt;/div&gt;&lt;p id=&quot;more14_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;14_0&#039;,&#039; more.. &#039;,&#039; less.. &#039;); return false;&quot;&gt; more.. &lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content14_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt; &lt;p&gt;iPhone SDK는 iPhone OS 를 위한 응용을 개발하고, 테스트하고, 수행하고, 디버그하고, 튜닝하는데 칠요로하는
코드, 정보, 도구를 포함하고 있습니다. Xcode 도구는 iPhone OS 를 위한 개발을 지원하기위해서 업데이트되었습니다.
기본적인 작성, 컴파일, 그리고 작성한 코드를 위한 디버깅 환경을 제공하는 것뿐 아니라, Xcode는 당신의 로컬 매킨토쉬
컴퓨터에서 기본적인 iPhone OS 환경을 흉내내는 플랫폼인 iPhone 시뮬레이터에서 응용프로그램을 수행시킬 수 있습니다.&lt;/p&gt;
&lt;p&gt;본 문서에서는 iPhone OS에서 나타나는 기본적인 특징들에 대해서 높은 수준의 오버뷰를 제공하여, 독자가 플랫폼에
익술할 수 있도록 도울 것입니다. 사용자는 iPhone Dev Center에서 다른 분서를 통해서 빠르게 배우고, iPhone
응용프로그램을 만드는데 기본 프로세스를 이해할 수 있도록 도울 것입니다. 독자는 이러한 본서들을 통해서 iPhone OS 를
위한 배움의 길을 안내하는데 사용해야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;iPhone OS Technology Layers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;iPhone OS에서는, 하부의 시스템 구조와 많은 기술들이 Mac OS X 에서의 기술들과 유사합니다. iPhone
OS의 커널은 Mac OS X에서 발견할 수 있는 기본적으로 같은 Mach 커널의 변종에 기반을 두고 있습니다. 이러한
커널위에는 플랫폼 상에서 응ㅇ요프로그램을 구현하는데 사용되는 서비스들의 레이어가 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: rgb(136, 136, 136);&quot;&gt;그림 1. iPhone OS 기술 레이어&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://cfs6.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNi50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTUwMDAwMDAwMDAxLmpwZw==&quot; width=&quot;260&quot; height=&quot;153&quot; /&gt;&lt;/p&gt;
&lt;p&gt;그림 1은 이러한 레이어들의 고수준 오버뷰를 나타냅니다. 이러한 레이어링은 당신이 코드를 작성할때 선택을 할 수 있게
합니다. 예를 들어, Core OS와 COre Services 레이어들은 iPhone OS의 필수적인 인터페이스 (파일을
접근하는데 사용하는 인터페이스, low-level 데이터 타입들, 봉쥬르 서비스들, 네트워크 소켓 등등)를 포함하고 있습니다.
이러한 인터페이스들은 대부분 C 기반이고, Core Foundation, CFNetwork, SQLite, 그리고 POSIX
쓰레드로의 접근와 UNIX 소켓들과 같은 기술들을 포함하고 있습니다.&lt;/p&gt;
&lt;p&gt;개발자가 상위레이어로 움직이려면, C 기반과 Objective-C 기반의 인터페이스를 혼용하여 사용하는 더욱 고급 기술들을
찾을 수 있습니다. 예를 들어, 미디어 레이어는 2D와 3D 드로잉, 오디오, 그리고 비디오를 기원하는데 사용되는 기본적인
기술을 포함하고 있습니다. 본 레이어는 C기반의 기술인 OpenGL ES, Quartx, 그리고 Core Audio를 포함하고
있습니다. 이는 역시 진보한 Objective-C기반의 에니메이션 엔진인 Core Animation를 포함하고 있습니다.&lt;/p&gt;
&lt;p&gt;Cocoa Touch 레이어에서는 대부분의 기술들이 Objective-C를 이용합니다. 이 레이어의 프레임워크에서는
작성하는 응용에서 사용되는 기본적인 인프라를 제공합니다. 예를 들어, Foundation 프레임워크는 콜렉션, 파일 관리,
네트워크 오페레이션, 그리고 그이상을 위해서 객체지향적 접근을 지원합니다. UIKit 프레임워크는 개발자의 응용프로그램을 위한
시각적인 인프라를 제공하는데 이는 윈도, 뷰, 컨트롤 그리고이러한 객체들을 관리하는 컴트롤러를 포함합니다. 이 레벨의 다른
프레임워크들은 사용자의 Contact 와 Photo 정보에 접근하는 방법을 제공하고, 디바이스의 다른하드웨어 특징과 가속계등에
접근하는 방법을 제공합니다.&lt;/p&gt;
&lt;p&gt;어떤 새로운 프로젝트를 시작하던지, 시작 지점은 Cocoa Touch 레이어이고, UIKit 프레임워크는 부분적으로 사용될
수 있습니다. 추가적인 기술을 사용하기로 결정했을 때에는, 보다 고수준의 레이어에 존재하는 프레임워크에서 시작하여 필요에 따라서
낮은 레이어의 프레임워크들로 내려오는 것을 추천합니다. 보다 높은 수준에 존재하는 프레임워크들은 작성해야하는 파트에 대해서 적은
노력으로 표준화된 시스템 행위 (behavior)를 지원하기 쉽게 만들어져 있습니다. 개발자가 보다 저수준의 프레임워크들로
내려가야만 할 때는 고수준에서 제공하지않는 custom behavior를 구현해야할 때입니다.&lt;/p&gt;
&lt;p&gt;더 자세한 내용은 &lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/index.html/index.html&quot; title=&quot;iPhone OS Programming Guide&quot;&gt;iPhone OS Programming Guide&lt;/a&gt; 를 참조하세요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;iPhone OS를 위한 코드 작성하기&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;iPhone SDK는 iPhone OS에서 네이티브하게 동작하는 그래픽을 지향한 응용들의 개발을 지원합니다. 작성한
응용프로그램은 사용자워 홈 스크린에 존재합니다 (물론 Photos, Weather, 그리고 CLock과 같은 다른 시스템
응용프로그램들과 함께..). 작성한 프로그램이 수행되고 나면 kernel과 소수의 저수준 대몬들을 제외하고, 작성한
응용프로그램만이 시스템 상에서 수행되게 됩니다. 수행되는 동안, 당신의 응용프로그램은 전제 스크린을 차지하고 사용자의 개입에
포커싱하게 됩니다. 사용자가 홈 버튼을 누르면, 작성한 응용프로그램은 나가게 되고 시스템은 다시 Home 화면을 보여줍니다.
개발자 자신의 시스템을 구축하는 것이 좋은데 왜냐하면 이는 개발자에게 하부 시스템 자원들에 대한 완전한 접근을 허용하기
때문입니다. 개발자는 개발자의 코드를 수행하는 가속계, 카메라, 그리고 그래픽하드웨어와 같은 내장된 하드웨어의 잇점을 이용할 수
있습니다.&lt;/p&gt;
&lt;p&gt;iPhone 와 iPod touch 디바이스들이 사용자와 상호작용하는 방식이 Mac OS X와의 사용자 상호작용와 다름으로
인해서, 개발하는 응용프로그램의 설계하는 방법 역시 달라져야 합니다. iPhone 응용은 컨텐츠를 표시하기 위한 다큐먼트 윈도를
분리한다는 개념 자체가 없습니다. 대신, 모든 응용프로그램의 데이터들은 하나의 윈도우에 표현됩니다. 이는 새로운 뷰와 개발자로
하여금 작성된 응용프로그램의 데이터가 잘 조직화되어 제공되도록 제어하는 것을 유도합니다. 추가적으로 많은 표준화된 뷰와 컨트롤은
그들의 Mac OS X 상대와 다르게 움직일 수 있습니다. 대부분의 이러한 변화는 투명해야하나, 일부는 개발자로 하여금 데이터를
조직화하고 표현하는 방법에 대한 재고를 요구하기도 합니다. iPhone OS에서의 event-handling model은
전통적인 데스트탑 응용프로그램으로부터 현격한 이탈을 보여줍니다. 전통적으로 마우스와 키보드 이밴트에 의존하는 것 대신에,
iPhone OS는 Touch 이벤트에 대한 아이디어를 도입했습니다. Touch event는 언제든지 하나 혹은 그이상의
추가적인 touch 이벤트들과 복합되어 나타날 수 있습니다. Touch들은 아이템들을 선택하거나 끄는 것과 같은, 컨텐트를
가지고 간단한 인터액션하는 것을 인식하는데 사용될 수 있고, 혹은 swipes 혹은 pinch-open 과 pinch-close
제스츄어들과 같은 복잡한 제스츄어와 언터액션들을 인식하는데 사용될 수 있습니다.&lt;/p&gt;
&lt;p&gt;작성하는 응용프로그램의 기본적인 구조에 대한 고려를 넘어서, 개발자는 사용자가 어떻게 실제로 응용프로그램을 사용할까에
대해서 생각할 필요가 있습니다. iPhone 응용프로그램들은 깨끗하고, 순간적으로 사용자가 무었을 필요로하는지에 대해서
집중해야만 합니다. 기억하십시요. 즉각적인 사용을 원하는 사용자는 정보를 빨리 얻기를 원하고 화면에 다수의 레이어를 이용해서
파해칠만한 시간적 여유를 가지고 있지 않다는 것을요. 게임이나 다른 재미난 응용들을 위해서는, 사용자는 역시 어떠헥 사용자들이
당신의 응용프로그램과 상호작용할지와 적절하게 카메라와 가속계와 같은 기술적 잇점을 적용할지를 고려해야만 합니다.&lt;/p&gt;
&lt;p&gt;개발을 사작하는 데 있어서, 처음으로 사용하길 원하는 프레임워크는 Foundation 과 UIKit 프레임워크들입니다.
이러한 프레임워크들은 모든 iPhone 응용프로그램들을 위한 중요한 서비스들을 제공합니다. 개발자가 개발자의 응용프로그램을
가다듦에 따라서, 시스템에 존재하는 다른 프레임워크들이 제공하는 서비스들을 연구해야 합니다. 각각 프레임워크에 대한 문서들은
해당 프레임워크를 어떻게 사용하는지에 대한 더맣은 정보를 제공하게 됩니다.&lt;/p&gt;
&lt;p&gt;Foundation 과 UIKit 프레임워크들에 대한 정보를 위해서 &lt;span style=&quot;color: rgb(85, 85, 85); font-family: &#039;Lucida Grande&#039;; font-size: 11px; line-height: 15px;&quot;&gt;&lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/ObjC_classic/index.html&quot; style=&quot;margin: 0px; padding: 0px; color: rgb(54, 96, 136); text-decoration: underline;&quot;&gt;Foundation Framework Reference&lt;/a&gt; &lt;/span&gt;와 &lt;span style=&quot;color: rgb(85, 85, 85); font-family: &#039;Lucida Grande&#039;; font-size: 11px; line-height: 15px;&quot;&gt;&lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIKit_Framework/index.html&quot; style=&quot;margin: 0px; padding: 0px; color: rgb(54, 96, 136); text-decoration: none;&quot;&gt;UIKit Framework Reference&lt;/a&gt; &lt;/span&gt;를 살펴보시기 바랍니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where to Start&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;iPhone OS에서 동작하는 간단한 응용프로그램을 만드는 것은 Xcode 에서 제공하는 내장된 프로젝트 템플릿을 이용하면
비교적 간단합니다. 하지만 의미있는 무언가를 하면서 멋지게 보이는 응용프로그램을 만들기 위해서는 제공되는 문서들을 읽어보는 것이
필요합니다. 적어도, 응용프로그램을 만드는 도구와 프로세스를 조사할 수 있는 iPhone Dev Center에 있는 다른
오리엔테이션 문서들을 읽어보길 바랍니다.&lt;/p&gt;
&lt;p&gt;만약 iPhone OS 와 Mac OS X 에 대해서 처음 접하는 사람이라면 iPhone OS의 기본 디자인 패턴과
컨벤션을 이해하는 것이 플랫폼을 위한 코드를 작성하는데 중요합니다. 응용프로그램들은 프레임워크에서 제공하는 파워의 잇점을 살렸을
때 최적화되어 돌아갑니다. 만약 기본 프레임워크 비헤비어간과한 상태에서 개발을 하려 한다면, 응용프로그램을 짜는데 있어서 간단한
디자인 패턴을 사용하도록 배우는 것보다 더욱 어려워질 수 있습니다. 모든 iPhone 개발자가 알아야하는 기본적인 정보는 &lt;span style=&quot;color: rgb(85, 85, 85); font-family: &#039;Lucida Grande&#039;; font-size: 11px; line-height: 15px;&quot;&gt;&lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/CocoaFundamentals/index.html&quot; style=&quot;margin: 0px; padding: 0px; color: rgb(54, 96, 136); text-decoration: underline;&quot;&gt;Cocoa Fundamentals Guide&lt;/a&gt; &lt;/span&gt;에 있습니다. 이 문서는 Objective-C의 기본과 프로그래밍 컨벤션들 그리고 UIKit 와 많은 다른 시스템 프레임워크에서 사용되는 디자인 패턴을 담고 있습니다.&lt;/p&gt;
&lt;p&gt;한번 기본 컨벤션들을 이해하고 응용프로그램을 작성해보았다면 더욱 자세한 개발 프로세스를 위해서 &lt;span style=&quot;color: rgb(85, 85, 85); font-family: &#039;Lucida Grande&#039;; font-size: 11px; line-height: 15px;&quot;&gt;&lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/index.html&quot; style=&quot;margin: 0px; padding: 0px; color: rgb(54, 96, 136); text-decoration: none;&quot;&gt;iPhone OS Programming Guide&lt;/a&gt; &lt;/span&gt;를
참조할 수 있습니다. 이 책은 중요한 개념과 태스크 기반의 정보를 iPhone 응용프로그램을 작성하는 입장에서 제공하고
있습니다. 그리고 어떻게 사용자 인터페이스를 표시하고, 이벤트들을 다루고, 중요한 iPhone 의 특징의 잇점을 살리는지에 대한
예제를 포함하고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: rgb(85, 85, 85); font-family: &#039;Lucida Grande&#039;; font-size: 11px; line-height: 15px;&quot;&gt;&lt;a href=&quot;http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/index.html&quot; style=&quot;margin: 0px; padding: 0px; color: rgb(54, 96, 136); text-decoration: none;&quot;&gt;iPhone OS Programming Guide&lt;/a&gt;&lt;/span&gt;
에 추가하여 가용한 샘플코드를 볼 수 있습니다. iPhone OS는 실 세계 응용프로그램을 작성하기 위한 가능한 기술들을 어떻게
사용하는지를 보여주는 몇개의 완전한 샘플들과 같이 제공되고 있습니다. 개발자는 이러한 샘플을 이용해서 자신의 응용프로그램에 대한
시작지점으로 삼을 수 있고, 특정한 특징을 어떻게 이용할 수 있는지에 대해서 살펴볼 수 있을 것입니다.&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;</description>
			<category>wkoh+apple</category>
			<category>iPhone</category>
			<category>sdk</category>
			<author>wkoh</author>
			<guid>http://www.v12n.info/14</guid>
			<comments>http://www.v12n.info/14#entry14comment</comments>
			<pubDate>Fri, 07 Mar 2008 12:04:18 +0900</pubDate>
		</item>
		<item>
			<title>asmlinkage</title>
			<link>http://www.v12n.info/12</link>
			<description>친구랑 이야기 하다가 asmlinkage 에 대해서 말이 튀어나왔다. 사실 예전에 os 수업때 system call 을 만들면서 사용했던 매크로인 것 같은데.. 하면서 xen 의 source 에서 definition을 찾아보았다.&lt;br /&gt;
&lt;br /&gt;#if defined(__x86_64)&lt;br /&gt;
...&lt;br /&gt;
#define asmlinkage&lt;br /&gt;
...&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;...&lt;br /&gt;
#elif defined(__i386__)&lt;br /&gt;
...&lt;br /&gt;
#define asmlinkage __attributre__((regparm(0)))&lt;br /&gt;
...&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;i386에서 해당 기능을 보자면... kernelnewbies 에서는 다음과 같이 나와있다.&lt;br /&gt;
&lt;br /&gt;&quot;This is a #define for some gcc magic that tells the compiler that the function should not expect to find any of its arguments in registers (a common optimization), but only on the CPU&#039;s stack.&quot;&lt;br /&gt;
&lt;br /&gt;이말인 즉슨... 원래 다들 알다시피 기본적으로는 function call 을 할 때 stack을 통해서 call를 하게 되어있다. 하지만 일부 컴파일러에서 optimization을 하면서 이를 register를 통해서 call 하도록 변경하는 경우가 발생하는데... 이부분은 이렇게 하면 안된다~ 라고 이야기 하고 있는 부분이다. 즉, CPU&#039;s stack에서만 아규먼트를 찾아야지, register에서 찾아서는 안된다. 라고 언급하고 있는 부분이 된다. &lt;br /&gt;
&lt;br /&gt;하지만 이러한 부분은 x86_64 와 i386에서 다르게 처리하고 있다. xen hypervisor 의 소스를 보자면...&lt;br /&gt;
&lt;br /&gt; - arch/x86/traps.c&lt;br /&gt;
1124  */&lt;br /&gt;
1125 &lt;span style=&quot;FONT-WEIGHT: bold&quot;&gt;asmlinkage&lt;/span&gt; void do_early_page_fault(struct cpu_user_regs *regs)&lt;br /&gt;
1126 {&lt;br /&gt;
1127     static int stuck;1128     static unsigned long prev_eip, prev_cr2;&lt;br /&gt;
1129     unsigned long cr2 = read_cr2();&lt;br /&gt;
&lt;br /&gt;역기서 i386의 경우에는 asmlinkage 가 위에서와 같이 정의된 형태로 해석이 될터이고, x86_64에서는 empty 로 정의가 되었으니 아무것도 없게 해석될 것이다. 이에 대해서 실제 early_page_fault 를 호출하는 부는 어떻게 되어있나 살펴보면...&lt;br /&gt;
&lt;br /&gt; - arch/x86/x86_32/entry.S &lt;br /&gt;
539 ENTRY(early_page_fault)&lt;br /&gt;
540         SAVE_ALL(1f,1f)&lt;br /&gt;
541 1:      movl  %esp,%eax&lt;br /&gt;
542         pushl %eax&lt;br /&gt;
543         call  do_early_page_fault&lt;br /&gt;
544         addl  $4,%esp&lt;br /&gt;
545         jmp   restore_all_xen&lt;br /&gt;
&lt;br /&gt;와 같이 arguments를 STACK에 저장하고 이를 해당 call을 수행하게 된다. 이때, call은 asmlinkage를 사용하고 있고 i386에서는 asmlinkage 가 empty가 아니기 때문에, call 의 arguments를 stack에서 찾게 된다.&lt;br /&gt;
&lt;br /&gt; - arch/x86/x86_64/entry.S &lt;br /&gt;
580 ENTRY(early_page_fault)&lt;br /&gt;
581         SAVE_ALL&lt;br /&gt;
582         movq  %rsp,%rdi&lt;br /&gt;
583         call  do_early_page_fault&lt;br /&gt;
584         jmp   restore_all_xen&lt;br /&gt;
&lt;br /&gt;하지만 위와 같이 i386이 아닌 x86_64 시스템에서는 그렇지 않음을 볼 수 있다. 이는 구조에 따른 calling convention에 관련된 문제인 듯하다. 실제 x86_64 구조에서는 calling convention에서 1~4번 파라메터의 경우, 레지스터에 넣고 5번부터는 stack에 넣어서 처리하게 되어있다고 한다. 하지만 callee가 stack을 이용해서 처리할 때를 대비하여 stack상에 4개의 파라메터를 위한 0x20 (32bytes)사이즈의 stack 공간을 예약한다고 한다.&lt;br /&gt;
&lt;br /&gt;linux kernel 상에서는 asmlinkage 에 대해서 define 되어있는 구조는 i386 뿐이며, ia64의 경우에는 __attributre__((syscall_linkage))로 선언되어 있고, 나머지에 대해서는 empty 로 defined 되어 있다고도 한다.</description>
			<category>wkoh+development</category>
			<category>Kernel</category>
			<category>Linux</category>
			<author>wkoh</author>
			<guid>http://www.v12n.info/12</guid>
			<comments>http://www.v12n.info/12#entry12comment</comments>
			<pubDate>Tue, 04 Mar 2008 18:31:10 +0900</pubDate>
		</item>
		<item>
			<title>Current I/O Virtualization (IOV) Techniques</title>
			<link>http://www.v12n.info/10</link>
			<description>&lt;p&gt;아래 &lt;a href=&quot;http://virtualization.tistory.com/9&quot;&gt;VMM Software Architecture Options&lt;/a&gt;&amp;nbsp;글에 이어지는 글로 &quot;&lt;em&gt;Intel Virtualization Technology for Directed I/O&lt;/em&gt;&quot;의 한 챕터입니다.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font size=&quot;3&quot;&gt;Current I/O Virtualization (IOV) Techniques&lt;br /&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;I/O 장치를 가상화할때, 하부의 가상화 소프트웨어는 해당 장치를 위해서 몇가지 종류의 오퍼레이션을 서비스해야한다. 소프트웨어와 물리 장치들간의 interaction은 다음과 같다.&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Device discovery: 소프트웨어가 플랫폼상의 장치들을 discover, query, 그리고 configure 할 수 있는 메커니즘 
&lt;/li&gt;&lt;li&gt;Device control: 소프트웨어가 장치와 통신하고 I/O 작업을 초기화하는 메커니즘 
&lt;/li&gt;&lt;li&gt;Data transfers: 장치가 data를 시스템 메모리 로부터/로의 전송하는 메커니즘. 대부분의 장치들은 data를 전송하기 위해서 DMA를 지원하고 있다. 
&lt;/li&gt;&lt;li&gt;I/O interrupts: 하드웨어가 이벤트와 상태 변경을 소프트웨어에게 알릴수 있는 메커니즘 &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;이러한 interaction들 각각은 공통된 가상화 기술의 각각에 대해서 discussion, covering implementation, 극복점, 장점, 단점을 가지고 있다. VMM은 하나의 monolithic 소프트웨어 스택 혹은 hypervisor와 특별한 guest들의 조합이 될 수 있다.&lt;/p&gt;&lt;p id=&quot;more10_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;10_0&#039;,&#039; more.. &#039;,&#039; less.. &#039;); return false;&quot;&gt; more.. &lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content10_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt; &lt;p&gt;&lt;strong&gt;Emulation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Native 플랫폼에서의 I/O 메카니즘은 일반적으로 하드웨어 장치의 일부 종류에서 수행된다. 소프트웨어 스택 (흔히
말해서 OS의 드라이버)는 memory-mapped (MMIO) 메커니즘의 일부 종류를 통해서 하드웨어와 인터페이스하게 되고,
프로세서는 특정한 메모리 (혹은 포트) 주소 범위에 읽기와 쓰기를 하는 instruction들을 issue하게 된다. 값을 읽고
쓰는 것은 하드웨어의 direct function들에 의해서 대응된다.&lt;/p&gt;
&lt;p&gt;에뮬레이션이란 소프트웨어에서 실제 하드웨어를 완전히 구현하는 것을 의미한다. 이의 큰 장점은 기존에 존재하는 guest
소프트웨어에 대해서 어떻한 변경도 요구되지 않다는 점이다. 소프트웨어가 native인 환경에서 수행하듯이 수행하게 되고 VMM
에뮬레이터와 interacting하면서 마치 실제 하드웨어와 동작하는 것처럼 동작을 하게 된다. 소프트웨어는 실제로 가상화된
장치와 이야기하는 것인지를 인식하지 못한다. 이러한 에뮬레이션이 동작하기 위해서는 몇몇 메커니즘들이 필요하다.&lt;/p&gt;
&lt;p&gt;VMM은 guest 소프트웨어에 의해서 discovered 될 수 있는 것과 동일한 방식으로 장치를 표출시켜야만 한다.
예를 들어, PCI 설정 공간에 있는 장치가 있다면, guest 소프트웨어는 device를 볼 수 있고, 장치와
interact하는데 사용되는 메모리 공간을 찾을 수 있게 된다.&lt;/p&gt;
&lt;p&gt;VMM은 또한 device-discovery 공간에 접근을 capturing 하는 것은 물론 장치의 주소 범위에 read
와 write들을 capturing하는 일부 메소드를 갖고 있어야만 한다. 이는 VMM으로 하여금 guest 소프트웨어가
인터테이싱하고 있다고 믿고 있는 진짜 하드웨어를 에뮬레이트하는 것을 가능하게 한다.&lt;/p&gt;
&lt;p&gt;(일반적으로 장치 모델이라 불리는) 장치는 소프트웨어로 VMM에 의해서 완전히 구현된다. 이는 일부 I/O를 서비스하는
것과 동일한 방법으로 플랫폼에서 하드웨어의 일부 부분을 접근할수도 있으나, 해당 하드웨어는 실제 장치 모델과는 관계는
독립적이다. 예를 들어 guest가 VMM에 의해서 표출된 IDE 하드 디스크 모델을 볼수 있는 반면, 실제 플랫폼은 SATA
디스크를 제공하곤 한다는 것이다.&lt;/p&gt;
&lt;p&gt;VMM은 또한 에뮬레이트되는 장치의 일부로써 적절한 시기에 인터럽트들을 guest에게 주입(injection)할 수 있는
메커니즘을 가져야만 한다. 이는 일반적으로 PIC를 에뮬레이트하여 이뤄진다. 다시 말하자면 guest 소프트웨어가 PIC를
사용할 때, (guest의) 이러한 접근은 trap되어야만 하고, PIC 장치에 대한 에뮬레이트가 VMM에 의해서 적절히
수행되어야 한다. PIC가 단지 또 다른 하나의 I/O 장치로 생각되는 반면, 적절하게 에뮬레이트되는 임의의 다른
interrupt-driven I/O 장치도 존재해야만 한다.&lt;/p&gt;
&lt;p&gt;에뮬레이션은 VM의 하나의 플랫폼에서 또 다른 하나의 플랫폼으로의 이주를 용이하게 한다. 장치가 완벽하게 에뮬레이트되고
있고, 플랫폼 상에서 어떠한 physical 장치들에도 (직접적으로) 묶여있지 않기 때문에, VM을 VMM이 정확하게 똑같은
에뮬레이션되는 장치들을 지원하는 또다른 플랫폼으로 이동하는 것이 간단해진다. 만약 guest VM이 어떠한 플랫폼 물리 장치들에
일부 엮여 있다면, 이러한 같은 physical 장치들이 VM이 이주될 임의의 플랫폼에 존재해야할 필요가 있다.&lt;/p&gt;
&lt;p&gt;에뮬레이션은 역시 같은 종류의 플랫폼 물리 장치들의 공유를 용이하게 한다. 이는 에뮬레이션 모델의 인스턴스들이 많은
guest들에 잠재적으로 표출될 수 있기 때문이다. VMM은 하나의 물리 장치에 대한 모든 guest들의 에뮬레이션 모델 접근을
허용할수있는 공유 메커니즘을 일부에 사용할 수 도 있다. 예를 들어 에뮬레이션되는 네트워크 아답터들을 이용하는 많은
guest로부터의 traffic은 platform의 물리 네트워크 아답터로 브릿지 될 수 있다는 것이다.&lt;/p&gt;
&lt;p&gt;에뮬레이션이 guest 소프트웨어에게 일부 존재하는 물리 하드웨어 장치와 동일한 인터페이스를 제공하기 때문에, OS
독립적인 방법을 사용하여 다수의 서로 다른 guest OS들을 지원할 수 있게 된다. 예를 들어 특수한 저장장치가 완벽하게
에뮬레이트된다면, guest OS 가 windows xp건, linux이건 혹은 또다른 어떠한 IA기반의 OS 이건간에 상관없이
모든 소프트웨어가 해당 장치를 문제없이 사용하게 해준다. 대부분의 modern 운영체제들은 잘 알려진 장치들에 대한 드라이버를
기본적으로 제공하고 있기 때문에, 특별한 장치들의 경우에도 에뮬레이션을 통해서 기존의 legacy 환경에서도 사용이 가능해 진다.&lt;/p&gt;
&lt;p&gt;에뮬레이션이 guest 장치 드라이버를 수정할 필요가 없는 등의 이러한 장점에도 불구하고, 이의 가장 큰 문제점은 성능이
낮다는 점이다. 에뮬레이트된 장치의 guest 장치 드라이버 각각의 interaction은 VMM으로의 transition을
요구하게 되고, transition 후 장치 모델은 필요한 에뮬레이션을 진행하게 되며, 에뮬레이션이 진행된 후 적절한 결과를
가지고서 guest로 transition back하게 된다. 에뮬레이트되는 I/O 장치들의 종류에 따라서 이러한
transaction들이 많이 필요하게 될수 있다. 이러한 움직임은 비-가상화 환경에서 일반적인 소프트웨어-하드웨어간의
interaction에 비해서 상당한 오버헤드를 더하게 된다. 각각 interaction을 진행한 시간은 역시 전체적인
latency를 높이게 된다.&lt;/p&gt;
&lt;p&gt;또 하나의 단점은 장치모듈은 하드웨어 장치를 매우 정확하게 에뮬레이트해야할 필요가 있다는 점이다. 종종 하드웨어의
revision 등, 모든 사소한 것까지 에뮬레이트해줘야하는 것이다. 이는 &#039;bug emulation&#039;까지 필요하다는 것을
의미하고, 하드웨어의 새로운 revision들로 인해서 문제는 계속 발생하게 된다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;font-weight: bold;&quot;&gt;Paravirtualization&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;가상 I/O의 또 한가지 테크닉은 guest에 존재하는 소프트웨어를 변경하는 방식으로
paravirtualization이라고 불리운다. I/O paravirtualization의 장점은 더 나은 성능이다. 반면
단점으로는 guest 소프트웨어의 변경을 필요로 한다는 점인데, 이는 특정 장치 드라이버에 대해서 legacy OS에서의
사용성에 의해 제한되기도 하고, 장치 드라이버에 의해 제한되기도 한다. Paravirtualization을 이용할 경우에는
수정된 guest 소프트웨어가 직접적으로 VMM과 통신하게 되는데, 이는 일반적인 하드웨어/소프트웨어 인터페이스보다 높은 추상화
수준을 이용하게 된다. VMM은 I/O 종류에 한정적인 API를 표출시키게 되는데, 예를 들어 네트워크 아답터의 경우에는
네트워크 패킷들의 send 와 receive를 표출시키게 된다. guest에서 변경된 소프트웨어는 하드웨어 장치 인터페이스와
직접적으로 통신하는 대신에 이러한 VMM API를 사용하게 된다.&lt;/p&gt;
&lt;p&gt;Paravirtualization은 guest OS와 VMM 간의 통신 수를 줄이게 됨으로써 장치 에뮬레이션에 비해서 높은 성능 (더 높은 처리량, 낮은 레이턴시, 낮은 CPU 사용율)을 제공하게 된다.&lt;/p&gt;
&lt;p&gt;에뮬레이트된 인터럽트 메커니즘 대신에, ㅖaravirtualization은 eventing 혹은 callback 메카니즘을
사용하고 있다. 이는 PIC 하드웨어와의 통신이 없어지고, 대부분의 운영체제의 핸들이 단계적으로 발생하는 것을 방해하여
오버해드와 레이턴시가 증가하기 때문에, 더 나은 성능을 낼 수 있는데 도움이 주게 된다. 첫번째로 인터럽트들은 작은
Interrupt Server Routine (ISR)에 의해서 운영된다. ISR 은 일반적으로 인터럽트에 대해서 알고 있고
이를 적절한 worker task에게 할당하게 된다. worker task는 그러면 다른 context 하에서 인터럽트와 관련된
다수의 work를 수행하게 된다. VMM에 의해서 guest 소프트웨어에서 직접적으로 초기화된 event 와 callback 을
이용해서 work는 같은 context 안에서 직접 처리된다. 일부 구현에서는 VMM이 guest 에게 interrupt 를
전달할 때, VMM은 동작하고 있는 guest가 VMM으로부터 나오도록 강제해야 하고, guest가 재진입할 때, 대기하고 있는
interrupt들이 처리될 수 있도록 하고 있다. 동작하고 있는 guest를 강제로 나오도록 하기 위해서, IPI 와 같은
메커니즘이 사용된다. 그러나 이는 다시 direct callback이나 event 와 비교해서 큰 오버헤드를 더하게 된다. 다시
말하자면 이러한 접근의 가장 큰 단점은 guest OS kernel 의 interrupt 처리 메커니즘들이 변경되야 한다는
것이다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;Figure 1. Device paravirtualization.&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://cfs5.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTQwMDAwMDAwMDAwLmpwZw==&quot; width=&quot;187&quot; height=&quot;270&quot; /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Figure 1에서 보이는 바와 같이, Paravirtualization 은 guest 소프트웨어를 수정해야 하기 때문에,
일반적으로 수정된 컴포넌트들은 guest environment에 제한된다. 예를 들어, windows xp용
paravirtualized storage 드라이버는 linux environment 에서 동작하지 않는다. 그러므로, 분리된
paravirtualized 컴포넌트는 각각 대상 guest environment 를 위해서 개발/지원되어야만 한다. 이러한
변경은 특정한 VMM에 의해서 지원되는 guest environment 에 대한 연역적인 지식을 필요로 한다.&lt;/p&gt;
&lt;p&gt;장치 에뮬레이션과 같이, paravirtualization은 VM 이주를 지원하는데, 이때 guest 소프트웨어 스택이 필요로 하는 동일한 VMM API들을 지원하는 플랫폼으로의 이주만을 제공하게 된다.&lt;/p&gt;
&lt;p&gt;같은 종류의 어떠한 플랫폼 물리 장치들의 공유는 에뮬레이션과 동일한 방식으로 지원된다. 예를 들어,
paravirtualized storage 드라이버를 이용해서 guest 가 데이터를 읽고 쓰기를 할 때 VMM에 의해서
관리되는 동일한 물리 스토리지 장치상의 공간을 사용할 수 있다. Paravirtualization은 점차
I/O-intensive 응용들의 성능 요구조건을 만족시키도록 배포되고 있다. 네트워킹, 스토리지, 그리고 고성능 그래픽과 같은
성능에 민감한 I/O 클래스들의 paravirtualization은 modern VMM 구조의 선택의 방법이 될 수 있다.
설명한 바와 같이, I/O 의 paravirtualization은 장치 에뮬레이션으로 인한 다수의 프로세싱을 없을 뿐 아니라,
클라이언트 VM 과 VMM 간의 transition의 수를 감소시킨다.&lt;/p&gt;
&lt;p&gt;Paravirtualization은 guest OS 에서의 I/O 인터페이스를 위한 고수준 추상화를 제공한다. 가상화되고
있다는 사실을 인지하고 있는 I/O 버퍼 할당과 관리 정책들은 완전한 장치 에뮬레이션에 의존하는 수정하지 않은 드라이버로서
가능한 것보다 VT-d 보호와 변환 기능을 더욱 효율적으로 사용할 수 있도록 한다.&lt;/p&gt;
&lt;p&gt;적어도 세 주 VMM 회사들은 높은 확장성과 성능을 위해서 I/O 를 paravirtualize 하는 capability
을 적용하고 있다. Xen 과 VMware 는 이미 paravirtualized I/O 드라이버들을 사용하고 있고, MS도 역시
차세대 VMM에서 I/O paravirtualization의 포함을 계획하고 있다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Direct Assignment&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;플랫폼상의 물리 I/O 장치를 특정한 guest VM이 직접 소유하도록 원하는 경우가 있다. 에뮬레이션처럼, 직접
할당(direct assignment)는 장치를 소유하고 있는 guest VM이 표준 장치 하드웨어 인터페이스를 이용해서
직접적으로 (장치와) 인터페이스하는 것을 허용한다. 그러므로, 직접 장치 할당은 guest VM에게 native한 경험을
제공하는데, 이는 이미 존재하는 드라이버의 재사용이 가능하거나, 다른 소프트웨어가 장치에 직접적으로 통신하는 것을 지원하기
때문이다.&lt;/p&gt;
&lt;p&gt;직접 할당은 에뮬레이션보다 높은 성능을 제공하는데, 이는 guest VM 장치 드라이버들이 virtual emulated
device의 장치 명령어 포맷으로부터 변환을 하지 않아도 되고, 해당 native 하드웨어 명령 포맷으로 장치와 통신할 수
있게 되기 때문이다. 더 중요한 것은, 직접 할당은 VMM의 신뢰성을 높이고 VMM의 복잡도를 줄이는데, 이는 복잡한 장치
드라이버들이 VMM으로부터 guest로 옮겨갔기 때문이다. 그러나 직접 할당은 모든 사용에 적합하지는 않다. 첫째, VMM은
오직 플랫폼에 물리적으로 존재하는 수만큼의 장치만을 할당할 수 있다. 둘째, 직접 할당은 VM 이주를 매우 복잡하게 만든다.
플랫폼간의 VM 이주를 위해서, 유사한 장치 종류, 제조사, 그리고 모델이 각각 플랫폼에 꼭 존재해야만 하고 사용이 가능해야
한다. VMM은 역시 이주하기 전의 플랫폼으로부터 어떠한 물리 장치 상태를 알아내는 방법을 개발해야 하고, 이주할 대상
플랫폼에서 그 상태를 복원하는 방법 역시 개발되어야만 한다.&lt;/p&gt;
&lt;p&gt;게다가, 직접 할당을 지원하기 위한 하드웨어가 없기 때문에, 직접 할당은 성능 증가와 신뢰성 향상에 대한 잠재능력을 잃게
되었다. 그 첫째로, 플랫폼 인터럽트는 여전히 VMM에 의해서 처리되어야 한다. 이는 물리적인 플랫폼의 나머지를 VMM이
소유하고 있기 때문이다. 인터럽트들은 적절한 guest로 라우팅되어야만 하는데 - 이러한 경우에는 물리 장치를 하나만이 소유하게
된다. 그러므로 인터럽트들을 전달하는데 여전히 약간의 오버헤드가 남게 된다. 둘째, 기존에 존재하는 플랫폼들은 장치가 직접적으로
data 전송을 효율적이고 안전한 방법을 통해서 자신이 속한 guest VM에 속한 system memory 로 전송하는 기능을
제공하지 않는다는 점이다. guest VM은 기본적으로 실제 물리 주소 공간의 일부에서 운영된다. guest VM이 물리
메모리라고 믿고 있는 것은 실제로는 물리 메모리가 아니라, 이는 guest 를 위해서 VMM에 의해서 가상화된 시스템 메모리의
일부인 것이다. 이러한 addressing mismatch 는 DMA-capable 장치에 의해서 문제점을 야기시킨다. 그러한
장치들은 data를 CPU의 관여없이 system memory로 직접 위치시키는데, guest 장치 드라이버가 장치로 하여금
guest 물리 주소들을 이용하여 데이터 전송을 시키려고 할때, 반면 하드웨어는 host 물리 주소들을 이용해서 시스템 메모리를
접근하려 하게 된다.&lt;/p&gt;
&lt;p&gt;space space mismatch를 해결하기 위해서, 직접 접근을 혀용하는 VMM들은 guest VM 장치 드라이버와
하드웨어 장치간의 모든 통신에 대해서 intercept 들을 가하는 pass-through 드라이버를 사용하곤 한다.
pass-through 드라이버는 guest physical과 physical address들을 언급하는 모든 명령 아규먼트들의
real physical address space간의 번역을 수행한다. Pasds-through 드라이버는 장치-제한적인데,
이는 필요한 번역을 수행하기 위해서 특정 장치를 위한 명령 포맷을 해것해야만 하기 때문이다. 그러한 드라이버들은 전통적인 장치
드라이버들보다는 간단한 작업을 수행하게 되는데; 그러인하여 성능은 에뮬레이션에 비해서 높게 나타난다. 그러나, VMM의 복잡도는
여전히 높고, 그로 인해서 VMM의 신뢰성에 좋지 않은 효과를 가져온다. 여전히 성능 이득에 대해서, 서버 공간을 목표로 하여,
VMM에서 이러한 메소드를 도임합이 충분한 것으로 보이지만, 오직 비교적 작은 수의 공용 장치들만을 위한 직접 접근을 지원하게
되는 것도 사실이다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VMM Software Architecture Implications&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;다른 I/O 가상화 메소드들은 모든 VMM 소프트웨어 구조 선택에 동등하게 적용되지 않는다.&lt;/p&gt;
&lt;p&gt;에뮬레이션은 가장 일반적인 I/O 가상화 방법이고, 수정하지 않은 guest OS 에게 표준화된 I/O 장치들을 표출시키는
것이 가능하다. 그에 따라 기존의 OS-hosted, stand-alone hypervisor 혹은 hybrid VMM 구현에
많이 사용되고 있다.&lt;/p&gt;
&lt;p&gt;이미 언급한 바와같이, paravirtualization은 공통 guest들의 성능을 높이기 위해서 점차 많은 VMM들에
의해서 사용되고 있다. 이는 stand-alone hypervisor VMM들에 쉽게 적용이 됐다. 이는 guest OS 와
OS-hosted VMM안의 ULM간의 interaction에 역시 사용될 수 있고, hybrid VMM에서 guest OS 와
service VM에서 사용될 수 있다.&lt;/p&gt;
&lt;p&gt;직접 할당은, 수정하기 어렵거나 혹은 특정 응용을 위해서 paravirtualized guest 장치 드라이버들이 인정되지
않는 등으로 인한, guest OS를 수정할 수 없는 경우에 사용된다. 그러나, 일반적으로 그런 VMM들이 실제 플랫폼 장치들을
소유하고 있지 않고, 그런 장치들을 위한 장치 드라이버들을 유지보수하고 있지 않기 때문에, OS-hosted VMM에 직접
할당을 도입하는 것은 어려운 일이다. 다시 말하자면, 작접할당은 원천적으로 stand-alone hypervisor 와
hybrid VMM들에서 복잡도를 줄이는 데 사용되는데, 이는 장치드라이버들이 비교적 guest OS 혹은 service
OS들로 이동하기 쉽기 때문이다.&lt;/p&gt;
&lt;p&gt;하나의 VMM이 서로다른 다수의 I/O 가상화 기술들을 적용하는 것은 있을 법도 한 일이다. 예를 들어, hybrid
VMM에서 직접 할당은 특정한 guest VM에 플랫폼 물리 장치를 할당하는데 사용할 수 있는데, 이때 할당된 플랫폼 물리
장치는 다른 guest들을 위해서 공유되는데 사용될 수 도 있다. guest의 필요와 충분이라는 입장에서 보면, 다른
guest들에게 paravirtualized 솔루션들 뿐만 아니라, emulated 장치 모델들을 제공할 수도 있다. 공통적인
설정 방법으로는 대부분의 공통 guest environment 들을 위해서 paravirtualized 솔루션들을 제공하고,
반면 emulation 솔루션은 모든 다른 legacy environment 들을 지원하는데 제공하는 것이 되겠다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;IOVM Architecture&lt;/p&gt;
&lt;p&gt;가상화 소프트웨어 개발자들 간에 새롭게 나타난 주요한 트랜드는, 특히 I/O 프로세싱과 공유의 부분에서, VMM 시스템 decomposition이다.&lt;/p&gt;
&lt;p&gt;VMM들의 소프트웨어 구조의 트렌드는 monolithic hypervisor model에서 VMM을 물리적인 하드웨어 바로
위에 존재하는 매우 얇은 privileged &quot;micro-hypervisor&quot;와 hypervisor 에 비해
de-privileged 된 하나 혹은 그이상의 특별한 목적을 갖는 (service 들과 policy를 담당하는) VM들로
나누어진 소프트웨어 구조로 변화하고 있는 것이다. I/O 가상화를 고려한 입장에서, 이러한 VMM의 deprivileged
컴포넌트들은 I/O 프로세싱과 I/O 자원 공유에 책임을 지게 된다. 우리는 이러한 일반적인구조를 (Figure 2와 같이)
IOVM이라고 부른다. IOVM 모델은 특정 I/O 기능을 위해 특별히 만들어진 다른 service VM들에게 I/O 장치를
할당하는 hybrid VMM의 일종이라 볼수 있다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;Figure 2. IOVM 소프트웨어 구조&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://cfs5.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTQwMDAwMDAwMDAxLmpwZw==&quot; width=&quot;158&quot; height=&quot;193&quot; /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;IOVM 모델의 두 중요한 잇점은 IOVM 내의 수정되지 않은 장치 드라이버들을 사용할수 있는 것과 다른 guest
OS들, 응용들, 그리고 hypervisor 로부터 물리 장치와 그 다르이버(들)을 격리시킬 수 있다는 것이다. 수정되지 않는
드라이버의 사용은 이러한 드라이버들이, VMM 환경을 위해서 종종 새로 작성되어야 하는 드라이버들을 필요로 하는
monolithic hypervisor와는 다르게, 분리된 OS 환경이서 이러한 드라이버들을 수행할 수 있기 때문에 가능해진다.
장치와 그 드라이버의 격리는 guest VM들이 드라이버 crash로부터 보호받게되는데, 즉 IOVM이 드라이버의 failure
로 인해서 crash되어도 guest OS에 영향가지 않게 된다는 것이다. IOVM 모델의 단점은 guest OS 와
IOVM간의 data 이동과 추가적인 통신이 필요함으로 인해서 오버헤드가 부가된다는 점이다. 이러한 성능에 대한 불이익은
IOVM의 인터페이스를 paravirtualizing 함에 있어서 상쇄시킬 수 있고, 그럼으로 인해서 interaction의
수를 줄일 수 있다. Xen VMM은 이러한 구조를 &quot;Isolated Driver Domains&quot; 라는 이름으로 구현해왔고,
Microsoft도 그들의 차세대 VMM에서 이롸 같은 구조를 사용할 것으로 개발을 진행하고 있다.&lt;/p&gt;
&lt;p&gt;IOVM으로의 I/O 장치들의 직접 할당은 직접적으로 이러한 사용모델을 수월하게 하고, VMM들이 이러한 구조로 옮겨가는데
중요한 역할을 하고 있다. 그러나 우리가 볼수 있듯이, 소프트웨어 자신만으로는 VMM에서 발생하는 모든 장치-제한적 기능을
제거함과 동시에 I/O 장치와 system memory같의 잘못된 DMA traffic으로부터 system을 완벽하게 보호할
수는 없다. 플랫폼에서 하드웨어의 지원으로 IOVM에 장치가 안전하게 할당되도록 지원하여 이러한 gap을 없에고 있고,
그럼으로써 잘못된 DMA 전송으로부터 완전한 보호를 제공하게 된다.&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;참조&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Darren Abramson, &quot;Intel Virtualization Technology for Directed
I/O,&quot; Intel Technology Journal, Volume 10, Issue 03, August 10, 2006. &lt;/li&gt;&lt;/ol&gt;
&lt;br /&gt;&lt;br /&gt;</description>
			<category>wkoh+virtualization</category>
			<category>DMA</category>
			<category>I/O</category>
			<category>interrupt</category>
			<category>virtualization</category>
			<category>VMM</category>
			<author>wkoh</author>
			<guid>http://www.v12n.info/10</guid>
			<comments>http://www.v12n.info/10#entry10comment</comments>
			<pubDate>Mon, 03 Mar 2008 09:05:33 +0900</pubDate>
		</item>
		<item>
			<title>FAQ/DoWhile0</title>
			<link>http://www.v12n.info/11</link>
			<description>&lt;p&gt;커널 코드를 보다보면 #define do {...} while(0) 가 종종 쓰인다. 이러한 부분이 kernelnewbies.org 에 있어서 간단히 정리해 놓는다.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;(Dave Miller는) Empty statements의 경우 컴파일러가 warning으로 간주하기 때문에 dowhile0 블럭을 사용한다.&lt;/li&gt;

  &lt;li&gt;(Dave Miller는) local variables를 선언하는 basic block으로 간주할 수 있다.&lt;/li&gt;

  &lt;li&gt;(Ben Collins는) 이는 조건이 담긴 코드에서 보다 복잡한 메크로를 사용할 수 있도록 지원하다고 말하고 있다. 만약 몇줄로 이뤄진 하나의 매크로가 다음과 같다면...&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;#define FOO(x) \&lt;br /&gt;        printf(&quot;arg is %s\n&quot;, x); \&lt;br /&gt;        do_something_useful(x);&lt;br /&gt;&lt;br /&gt;이제 이러한 함수를 다음과 같이 사용할 때:&lt;br /&gt;if (blah == 2)&lt;br /&gt;        FOO(blah);&lt;br /&gt;&lt;br /&gt;이는 다음과 같이 해석된다.&lt;br /&gt;if (blah == 2)&lt;br /&gt;        printf(&quot;arg is %s\n&quot;, blah);&lt;br /&gt;        do_something_useful(blah);;&lt;br /&gt;&lt;br /&gt;여기서 보이다시피 원치않게도 do_something_useful은 조건문에 속하지 않게 된다. 그래서 &lt;br /&gt;dowhile0를 사용하여&lt;br /&gt;if (blah == 2)&lt;br /&gt;        do {&lt;br /&gt;                printf(&quot;arg is %s\n&quot;, blah);&lt;br /&gt;                do_something_useful(blah);&lt;br /&gt;        } while (0);&lt;br /&gt;와 같은 형태로 만드는 것이다.&lt;br /&gt;
&lt;/pre&gt;
&lt;ul&gt;
  &lt;li&gt;(Per Persson은) Muller 와 Collins가 지적한 바와 같이 block statement를 사용하길 원할때, 몇몇줄의 코드와 local variables를 선언할 수 있다고 언급했다. 그러나 일반적으로 사용할 때는 차라리 다음과 같이 사용하는 편이 더욱 직관적이겠다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }
&lt;br /&gt;그러나 이는 어떤 경우에 대해서는 정상적으로 동작하지 않는다. 다음 코드는 두개의 브랜치를 가지는 If-statement 이다.&lt;br /&gt;if (x &amp;gt; y)
        exch(x,y);          // Branch 1
else  
        do_something();     // Branch 2
그러나 이는 오직 하나의 브랜치만을 갖고있는 if-statement로 해석되게 된다. 다음과 같이...&lt;br /&gt;if (x &amp;gt; y) {                // Single-branch if-statement!!!
        int tmp;            // The one and only branch consists
        tmp = x;            // of the block.
        x = y;
        y = tmp;
}
;                           // empty statement
else                        // ERROR!!! &quot;parse error before else&quot;
        do_something();
&lt;br /&gt;블럭 뒤에 바로 나오는 semi-colone(;)이 문제가 된 것이다. 이에 대한 해결책은 역시 dowhile0를 사용하는 것이다. 그러면 블럭의 capabilities를 갖는 하나의 statement 를 사용하게 되는 것으로, 다음과 같이 해석될 것이다.&lt;br /&gt;if (x &amp;gt; y)
        do {
                int tmp;
                tmp = x;
                x = y;
                y = tmp;
        } while(0);
else
        do_something();
&lt;br /&gt;
&lt;/pre&gt;
&lt;ul&gt;
  &lt;li&gt;(Bart Trojanowski는) gcc는 dowhile0 블럭을 대체할 수 있는 &lt;a href=&quot;http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Statement-Exprs.html#Statement-Exprs&quot;&gt;Statement-Expressions&lt;/a&gt;를 제공하고 있다고 언급했다. 이는 위의 장점에 더욱 읽기 쉽다라는 추가적인 장점을 제공한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;#define FOO(arg) ({         \
           typeof(arg) lcl; \
           lcl = bar(arg);  \
           lcl;             \
    }) 
&lt;/pre&gt;</description>
			<category>wkoh+development</category>
			<author>wkoh</author>
			<guid>http://www.v12n.info/11</guid>
			<comments>http://www.v12n.info/11#entry11comment</comments>
			<pubDate>Fri, 29 Feb 2008 10:19:19 +0900</pubDate>
		</item>
		<item>
			<title>VMM Software Architecture Options</title>
			<link>http://www.v12n.info/9</link>
			<description>&lt;p&gt;가상화 레이어 (VMM) 소프트웨어 구조는 세가지 종류로 나워지는게 일반적이다&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;OS-hosted VMMs&lt;/li&gt;

  &lt;li&gt;Stand-alone hypervisor VMMs&lt;/li&gt;

  &lt;li&gt;Hybrid VMMs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;위에서 언급한 세가지 VMM 소프트웨어 구조 각각은 나름대로의 장점과 단점을 갖고 있고, 이는 주어진 사용 모델 혹은 시장 세그먼트에 따라서 선택되어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OS-hosted VMMs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;VMM 소프트웨어 구조로의 한 접근방법은 기존에 존재하는 OS의 인프라 위에서 구현되는 것이다. Figure 1의 VMM에서 보이는 바와 같이 이러한 OS-hosted VMM은 호스팅 OS의 커널 옆에서 수행되고 CPU와 시스템 메모리와 같은 시스템 자원의 제어를 얻어서 하나 혹은 그이상의 guest OS 들을 위한 수행 환경을 생성하는 privileged ring-0 콤포넌트로 구성된다. host-OS 와 guest-OS간의 VMM 커널의 컨텍스트 스위치는 쓰케줄링 정책에 기제되어 있는 주기적인 인터벌에 따라서 혹은 host-OS 의 지원이 필요로 하는 (예를 들어 host-OS 장치 드라이버로 프로그램된 물리 I/O 장치로부터의 하드웨어 인터럽트를 서비스한다던지...) 때 이뤄진다. guest OS 가 물리 CPU상에서 직접적으로 수행되고 VMM 커널의 제어를 받아 host physical 메모리의 특정부분을 직접적으로 수행되는 것이 허용되더라도, I/O 장치들로의 어떠한 접근이든지 기본적으로 VMM 커널에 의해서 인터셉트를 받게되고 VMM의 사용자 수준의 컴포넌트에 의해서 대행된다. (Figure 1의 ULM에서 나타나 있다.) TLM은 host OS의 일반적인 프로세스로 동작하고, guest OS 들로부터 발생하는 I/O 요청에 대해 서비스하는 가상 I/O 장치 모델을 포함하고 있다. ULM 내의 장치 모델은 guest OS들로부터릐 I/O 요청을 조작하는 파일시스템과 네트워킹, 그리고 그래픽 API를 통해서 하부의 host OS의 수행을 요청한다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  Figure 1. OS-hosted VMM&lt;br /&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;http://cfs5.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvOS5qcGc=&quot; width=&quot;227&quot; height=&quot;169&quot; alt=&quot;200802280951.jpg&quot; /&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
  OS-hosted VMM 구조는 다수의 장점을 제공한는데,
&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
  &lt;ol&gt;
    &lt;li&gt;VMM이 host OS 를 위해서 개발된 어떠한 I/O 장치 드라이버든지 사용이 가능하다는 점으로, 이는 서로 다른 physical host platform들로의 VMM 포팅이 쉽다는 것을 의미한다.&lt;/li&gt;

    &lt;li&gt;게자가 VMM은 host OS에서 제공하는 다른 기능들을 이용할 수 있다. 예를 들어 host platform의 전력관리 기능을 관리한다던지, I/O 자원의 발견을 한더던지 하는 scanning I/O bus를 위한 코드등을 사용할 수 있다.&lt;/li&gt;
  &lt;/ol&gt;

  &lt;p&gt;OS-hosted VMM 의 단점은 신뢰성, 가용성, 보안 등의 이슈가 모두 host OS 에 의해서 결정된다는 점이다. 만약 host OS 가 실패하거나 (일련의 문제로) 무조건 reboot 되어야 한다면 오든 다른 guest OS 들이 서비스를 할 수 없는 상황에 처한다는 점이다. OS-hosted VMM은 또한 VMM과 그 guest OS 뿐만이 아니라 host OS에서 운영되는 다른 응용들과 같이 host OS의 CPU 스케줄링 정책에 의해서 동작한다는 점이다. 만약 주어진 사용 모델이 보안, 가용성, 혹은 실시간 QoS에 관련된다면, 이러한 단점은 허용될 수 없게되기 때문에, 다른 VMM 소프트웨어 구조를 고려해야 할 것이다.&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;Stand-Alone Hypervisor VMMs&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;또하나의 대안이 될수 있는 접근은 VMM을 독립적으로 동작하는 hypervisor 의 형태로 구현하는 것으로써 이는 hosting OS에 의존하지 않게 된다. hypervisor 스타일의 VMM은 VMM 자신이 소유하는 I/O 장치 드라이버들, 장치 모델들, 그리고 스케줄러를 포함하고 있다.&lt;/p&gt;

  &lt;p&gt;hypervisor 스타일 VMM은 guest OS들의 QoS 만족과 스케줄링을 지원하도록 physical platform 자원들의 provisioning을 완전히 제어할 수 있다. hypervisor 스타일 VMM의 추가적인 장점은 I/O 서비스를 위해서 guest OS 요청으로부터 실제 physical I/O 장치 드라이버까지의 코드 패스가 OS-hosted VMM에 비해서 짧다는 점인데, I/O 요청을 수행함에 있어서 두 I/O 스택 (첫째로 guest OS 의, 그리고 두째로 host OS 의 )만을 필요로 한다. 게다가 hypervisor 커널의 사이즈를 제어하고 제한을 둠으로써 VMM은 확장된 보안과 더욱 작은 Trusted Computing Base (TCB)를 제공할 수 있게 된다.&lt;/p&gt;

  &lt;div style=&quot;text-align: center;&quot;&gt;
    Figure 2. Stand-alone Hypervisor VMM&lt;br /&gt;
  &lt;/div&gt;

  &lt;div style=&quot;text-align: center;&quot;&gt;
    &lt;img src=&quot;http://cfs5.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTAuanBn&quot; width=&quot;205&quot; height=&quot;165&quot; alt=&quot;200802281027.jpg&quot; /&gt;&lt;br /&gt;
  &lt;/div&gt;

  &lt;p&gt;hypervisor 스타일 VMM의 단점은 제한된 이식성의 손실이라는 점에서 기인하는데, 이는 어떠한 주어진 physical platform을 위해 필요로 하는 I/O 장치 드라이버들이 hypervisor 내에서 개발되어야 한다는 점이다. ACPI 기반의 시스템 전력 관리 (host VMM에서는 host OS의 것을 이요하기만 하면 되었던)와 같은 고급 시스템 기능을 역시 hypervisor 스타일 VMM 상에서도 재구현으 되어야 한다. 현재로서는 full modern OS만큼 복잡하지는 않지만, 성숙한 hypervisor기반 VMM은 시간이 지날 수록 훨씬 큰 사이즈로 커져가고 있고, (예를 들어, TCB 의 사이즈 제한을 통한 향상된 보안 과 같은) 앞에서 언급한 장점들을 조금씩 만족시켜가고 있다.&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;Hybrid VMMs&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;hypervisor 스타일 VMM구조의 보안과 신뢰성의 장점을 유지하면서 동시에 OS-hosted VMM 에서 처럼 존재하는 OS와 그에 관련된 장치 드라이버의 장점을 적용하기 위해서 일부 VMM들은 hybrid 접근법을 선택했다.&lt;/p&gt;

  &lt;div style=&quot;text-align: center;&quot;&gt;
    Figure 3. Hybrid VMM&lt;br /&gt;
  &lt;/div&gt;

  &lt;div style=&quot;text-align: center;&quot;&gt;
    &lt;img src=&quot;http://cfs4.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNC50aXN0b3J5LmNvbTovYXR0YWNoLzAvMTQwMDAwMDAwMDAwLmpwZw==&quot; width=&quot;221&quot; height=&quot;156&quot; alt=&quot;200802281037.jpg&quot; /&gt;&lt;br /&gt;
  &lt;/div&gt;

  &lt;p&gt;hybrid VMM 구조에서는 작은 hypervisor kernel (Figure 3에서 보이는 μ-Hypervisor)은 CPU와 메모리자원들을 제어한다. 하지만 I/O 자원들은 deprivileged 서비스 OS에서 동작하는 장치 드라이버들로 구현된다. VMM 안의 host OS의 장치 드라이버들과 유사한 방식으로 서비스 OS 는 동작하며 VMM은 기존의 존재하는 장치 드라이버들을 도입할 수 있게 된다. 이는 서비스 OS 가 μ-Hypervisor에 의해서 deprivileged되어 있다. 또한 VMM을 지원하면서 단독으로 동작하기 때문에 시스템 전체적으로 보안과 신뢰성 향상을 가능하게 한다.&lt;/p&gt;

  &lt;p&gt;hybrid VMM 구조는 hosted 와 hypervisor 스타일의 VMM의 좋은 성격만을 유지하여 제공하는 반면 새로운 문제점을 가지게 된다. μ-Hypervisor를 통해서 guest OS 와 service OS간에 잦은 privilege 수준의 transition으로 인한 새로운 성능 오버해드 등이 문제점으로 나타난다. 게다가 service OS 의 권한을 뺏은 (deprivilege)것에 대한 장점은 μ-Hypervisor를 통해서 장치 DMA 를 제어하는 하드웨어 지원을 통해서만 가능해진다는 점이다. 이러한 지원을 위해서 VT-d 와 같은 기술들이 사용된다.&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;참조&lt;/strong&gt;&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;Darren Abramson, &quot;Intel Virtualization Technology for Directed I/O,&quot; Intel Technology Journal, Volume 10, Issue 03, August 10, 2006.&lt;/li&gt;
  &lt;/ol&gt;&lt;br /&gt;
&lt;/div&gt;</description>
			<category>wkoh+virtualization</category>
			<author>wkoh</author>
			<guid>http://www.v12n.info/9</guid>
			<comments>http://www.v12n.info/9#entry9comment</comments>
			<pubDate>Thu, 28 Feb 2008 10:56:25 +0900</pubDate>
		</item>
		<item>
			<title>Intel Virtualization Technology for Directed I/O (VT-d)</title>
			<link>http://www.v12n.info/8</link>
			<description>
&lt;p&gt;어제 가상화에 관심있는 친구를 만나다가 IO 관련 가상화에 대해서 이야기를 조금 해보았는데... 그러면서 궁금해진 점이 virtualization technology for directed i/o 즉 VT-d 에 관련된 부분이었다.&lt;/p&gt;
&lt;p&gt;그래서 IOV (I/O Virtualization) 에 관련된 내용을 좀 찾아보았는데... 내용은 다음과 같았다.&lt;br /&gt;&lt;br /&gt;&lt;strong style=&quot;font-weight: bold;&quot;&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;I&lt;/span&gt;ntel Virtualization Technology for Directed I/O (VT-d)&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;VMM은 guest 소프트웨어로부터의 I/O requests에 대한 가상화를 지원하게 된다. 이를 위해서 현재 사용되고 있는 방법은 device emulation과 para-virtualization이다. 이러한 I/O device 가상화 (IOV) 모델에서, 신뢰성과 보호 수준에서 발생하는, 요구사항은 역시나 &lt;/p&gt;&lt;ol&gt;&lt;li&gt;VMM에 의해서 장치에 할당된 자원들에 대해서만 접근이 가능하고&lt;/li&gt;&lt;li&gt;격리(isolate) 를 제공해야 한다는 것이다.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;VT-d 는 이를 제공하기 위해서 hardware를 통해서 지원하는 가상화 기능으로&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;hardware assisted remapping 을 이용하여 장치 격리를 제공하고 이를 통한 reliability 와 security의 향상과, 
&lt;/li&gt;&lt;li&gt;장치들에 대한 직접적인 할당으로 인한 I/O 성능과 가용성의 증대 &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;그렇다면 hardware assisted remapping 이란 무엇일까?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;VT-d 는 장치들의 DMA를 미리 할당된 도메인 혹은 physical memory region들에 한정하는 기능을 제공한다. 이를 위해서는 DMA-remapping으로 알려져 있는 하드웨어 capability를 이용하게 된다. 칩셋의 VT-d DMA-remapping hardware logic은 DMA를 지원하는 peripheral I/O 장치들과 컴퓨터의 physical memory 간에 존재하게 되고, 이를 구현하기 위해서 computer system software로서 프로그램된다. (이를 가상화 환경에서는 VMM이 지원하게 되고, 가상화되어 있지 않은 환경, 즉 native 환경에서는 OS 가 이러한 기능을 구현하게 된다.) DMA-remapping은 incoming DMA request의 address를 현재 physical memory address로 변환하고, system software에서 제공하는 정보를 기반으로 해당 physical address에 접근이 가능한지를 검사하게 된다.&lt;/p&gt;
&lt;p&gt;Intel VT-d 는 system software가 여러개의 DMA protection domain들을 만들도록 지원한다. 각각 protection domain은 host physical memory의 일부를 할당받은 isolated environment이다. 여기서 DMA protection domain은 소프트웨어 사용 모델에 따라서 VM에 할당된 메모리로 나타나거나, 혹은 VMM의 일부로써 혹은 VM에서 수행되는 guest OS driver에 할당된 DMA memory로서 나타날 수 있다. VT-d 구조는 system software로 하여금, 하나 혹은 그 이상의 I/O device들을 하나의 protection domain에 할당할 수 있게 한다. DMA isolation은 address-translation 테이블들을 이용하여 해당 physical memory에 할당되지 않은 I/O 장치들로부터 protection domain의 physical memory로의 접근은 제한하여 제공된다. 이는 각각 가상 머신들의 컴퓨터 자원들간의 separation을 보장하도록 필요한 isolation을 제공한다.&lt;/p&gt;
&lt;p&gt;어떠한 주어진 I/O device가 임의의 memory location을 접근하려고 할때&lt;/p&gt;&lt;ol&gt;&lt;li&gt;DMA remapping hardware는 해당 device로부터 임의의 protection domain에 대한 접근 허용을 위해 address-translation table을 찾게 된다.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;만약 장치가 접근이 허용되는 range 밖의 주소에 접근을 시도하면, DMA remapping hardware는 그 접근을 막고, 시스템 소프트웨어에게 fault 를 report하게 된다.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;다음 Figure 1은 VT-d DMA Remapping을 보여주고 있는데, 여기서 Device-1은 Domain-C 에 할당되어 있지 않기에, Device-1이 Domain-C memory location range 를 접근하려고 시도할 경우 VT-d 하드웨어에 의해서 제한되게 된다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;Figure 1. VT-d DMA Remapping. &lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://cfs5.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvNi5qcGc=&quot; width=&quot;480&quot; height=&quot;161&quot; /&gt; &lt;/div&gt;&lt;br /&gt;여기서, 성능을 향상시키기 위해서, I/O device 들과 protection domain들간의 mapping, 그리고 DMA address translation의 page-table entries와 같은 자주사용되는 remapping-structure entries는 캐슁된다. 이에 대해서 VT-d는 Peripheral Component Interconnect Special Interest Group (PCI-SIG) Address Translation Services(ATS) 스펙을 지원하는데 이는 Endpoint Device에서 장치에 제한된 DMA translations에 대한 캐슁을 허용하는 방법을 표준화하고 있다. 
&lt;p&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I/O performance through Direct Assignment&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;가상화는 다수의 virtual machines을 하나의 서버에서 생성하도록 지원하고 있다. 이러한 consolidation은 server hardware utilization을 높이는 것이 사실이지만, 추가적으로 server application들의 consolidation으로 인해서 높은 I/O performance를 요구하게 된다. Software기반의 IOV 방법론들은 I/O device들의 emulation을 사용하고 있는데, 이러한 emulation layer를 이용하는 VMM은 hardware device의 VM들에 대한 일관된 view를 제공하고, 이를 통해서 물리적인 장치는 다수의 VM들에 의해서 공유되도록 지원한다. 그러나 이는 high I/O performance device들의 I/O performance를 낮추게 되는데, VT-d 는 VM에 대한 직접적인 device의 할당을 통해서 가상화된 I/O device의 native capability 와 native performance에 대한 손실에 대한 해결책을 제공하게 된다.&lt;/p&gt;
&lt;p&gt;이 모델에서는 VMM은 device들이 해당 파티션으로의 직접적인 할당을 가능하도록 하는 제어 기능에 대해서 일부 기능만을 수행하도록 한다. 즉, 파티션이 요청하는 모든 (혹은 대부분의) I/O request들을 진행하기 위해서 VMM이 호출되기 보다는, VMM은 guest software가 system functionality와 isolation에 관련된 조작을 하게 되는 protected resources (I/O configuration accesses, interrupt management 등과 같은)에 대한 접근을 진행하기 위해서만 VMM을 호출하게 된다.&lt;/p&gt;
&lt;p&gt;I/O device들의 직접 VM에 할당되기 위해서, VMM 은 DMA request들이 isolation되도록 강제해야 한다. 또한 이렇게 I/O device들이 도메인들에 할당될 때, DMA remapping hardware는 I/O device로부터 해당 도메인이 현재 소유하고 있는 physical memory에 대한 DMA만을 사용하도록 제한하는데 사용되게 된다.&lt;/p&gt;
&lt;p&gt;VM 혹은 guest 가 VMM 상에서 수행될 때, Guest Physical Address (GPA)로 알려져 있는, Guest OS의 physical address range로서 제공되는 address space는 실제 Host Physical Address (HPA)와는 같지 않을 수도 있다. DMA capable device들은 physical memory location들로부터/들로의 데이터 전송을 위해 HPA를 필요하게 된다. 그러나 direct assignment model에서는 guest OS device driver는 domain의 control하에 있게되고, DMA capable device이 필요로 하는 HPA 대신에 domain에 알고있는 GPA 를 제공하게 된다. 이때, VMM 은 DMA remapping hardware의 GPA to HPA 변환정보를 이용하여 필요한 변환을 수행하게 된다. 이러한 Remapping을 이용하여, data가 현재 중간에 존재하는 software emulation layer릍 통해서 전송되는 것이 아니라 guest들의 적절한 buffer로 직접적으로 전송될 수 있게 된다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;Figure 2. Software Emulation based I/O vs. Hardware based Direct Assignment I/O&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://cfs6.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNi50aXN0b3J5LmNvbTovYXR0YWNoLzAvNC5qcGc=&quot; width=&quot;480&quot; height=&quot;284&quot; /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Figure 2는 software emulation based I/O 와 hardware direct assignment based I/O 를 비교해 놓은 것이다. emulation based I/O에서는 중간의 software layer가 VM 과 device 간의 모든 I/O를 제어하는 것을 볼 수 있고, data가 emulation layer 를 통해서 device 로 전송되고 device로부터 emulation layer 로 전송되는 것을 보여준다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;direct assignment model에서는 unmodified guest OS driver가 해당 guest OS 에 할당된 device를 제어하는 것을 볼 수 있다. receive path에서 DMA remapping hardware는 guest OS driver에 의해서 제공되는 GPA를 옳은 HPA로 변환하고, 이에 따라 data는 guest OS의 버퍼로 직접적으로 전송되게 된다. VT-d 의 Interrupt Remapping 지원은 interrupt control 이 직접적으로 VM으로 할당되도록 허용하며, 이를 통해서 VMM의 overhead를 줄일 수도 있게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;strong&gt;Intel VT-d usage models&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;VT-d를 지원하는 OS들과 VMM들은 I/O memory management의 VT-d functionality를 사용하여 device가 system의 기능에 영향을 줄 수 있는 delinquent DMA를 수행하는 것을 방지하여 protection domain들로부터 device들을 격리시킬수 있게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;VT-d는 서버, 워크스테이션 그리고 software와 hardware의 결합에 의한 새로운 형태의 클래스에 대해서 보안을 제공하고 격리된 수행 공간인 virtual appliance라 불리는 컴포넌트를 수행함에 역시 사용될 수 있다. virtual appliance는 virus scanning과 firewall appliance 혹은 하드웨어 관리 appliance와 같이 미리 정의된 application들 그리고/혹은 service들을 위해서 최적화한 수행환경을 제공하게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;가상 환경에서의 VM들은 응용단에서부터 device단까지 protection domain들로 격리시킬 수 있다. 이러한 방법은 하나의 도메인에서 발생하는 하나의 I/O device에 대한 문제가 다른 도메인들에게 문제를 발생시키는 것을 격리시킬 수 있게 되고, IT 사용자로 하여금 더욱 나은 system reliability 와 uptime을 제공할수 있게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Test와 development 환경에서도 다수의 VM들을 사용한 서버와, 가상환경에서 동작하는 공존하는 다수의 OS들를 이용한 workstation들은 work partition들을 isolate시킴으로써 장점을 취하게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;strong&gt;Server Usage Models&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;많은 Server application들은 I/O-intensive 한데, 특히나 networking과 storage에 대해서는 더욱 그러하다. data center 내에서 생겨나는 중요한 I/O 요구사항들은 주로 scalability 와 performance인데, 이러한 부분은 mission-critical 응용들이 가상화된 data center server들과 infrastructure로 옮겨감에 따라서 server consolidation, reliability, 그리고 availability를 제공하기 위해서 필요하다. 또한 정부와 health-care는 동적인 health care 환경에서 mission-critical needs를 만족시키기 위해서 다수의 OS들을 제공하는 다수의 partition들에 대해서 secure I/O를 지원하고 isolation을 통해서 그 장점을 얻을 수 있다. 또한 health care에서 필요로하는 기관간의 개인 정보 보호에 관련된 보안에 대한 효과를 얻을 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;strong&gt;Enhancing Performance&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;가상화는 under-utilized server에 대해서 workload의 consolidation을 가능하게 해준다. 더욱 많은 work load가 consolidate됨에 따라서, I/O 의 사용과 bandwidth 가 많이 요구되고, I/O performance가 병목이 되게 된다. 성능을 높이기 위해서 높은 I/O 성능을 요구하는 VM에 대해서 직접적으로 전용의 고성능 I/O 장치가 할당될 수 있는데, Intel VT-d 기반의 I/O 가상화는 multi-port gigabit 그리고 10 gigabit 네트워크 아답터들과 같은 고성능 I/O 장치들로 하여금 platform상에 존재하는 다른 VM들이 고성능 장치의 동작에 영향을 주지 않도록 지원하게 된다. Intel은 PCI-SIG에서 I/O 가상화 스펙에 대해서 적극적으로 참여하고 있으며, 이는 다수의 VM들에 대해서 하나의 장치가 공유될 때에도 본연의 성능이 나오도록 지향하고 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;strong&gt;Enhancing Reliability and Security - Native OS and Server Consolidation&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;consolidated virtualized server들의 multiple I/O 장치들의 사용은 증가하고 있는데, 하나의 가상화된 서버에서 최대 네개의 networking 장치들이 사용되는 것이 찾기 어려운 일이 아니다. Intel VT-d 는 VMM들이 protected domain들에 대해서 이러한 device들을 isolate시킴으로써 reliability와 security 를 향상시키도록 돕게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;지정된 memory range에 대해서 device들의 접근을 제어함으로써 end to end (VM to device) isolation이 VMM에 의해서 제공된다. 이는 security reliability 그리고 availability를 향상시킨다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Device isolation은 비-가상화 플랫폼에서도 잘 적용될 수 있다. Device driver 개발자는 하드웨어 혹은 원치않는 memory range를 접근하는 device driver DMA를 debugging 하기 위해서 임의의 memory range들에 대해서 device isolation을 사용할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;strong&gt;Getting around &quot;Bounce Buffer&quot; Conditions&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Intel VT-d DMA remapping 기능을 사용한 시스템 소프트웨어는 bounce buffer conditions을 피함으로써 성능을 증가시킬 수 있다. bounce buffer들이 DMA를 수행하는 32bit device와 32bit address limitation들로 인해서 접근 불가한 physical memory range간에 사용될 때, 시스템 소프트웨어는 buffer 카피들을 수행하지 않고는 data를 high memory로의 data redirect를 사용할 수 있는데 이를 위해서 Intel VT-d DMA remapping을 사용할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;strong&gt;Client Usage Models&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Intel VT는 3rd party 회사로부터 필수적으로 필요한 security와 deep packet inspection과 Intel vPro technology를 이용한 desktop PC에서의 policy compliance 와 같은 activities를 위한 관리 서비스들을 수행하기 위해서 virtual appliance의 배포를 가능하게 한다. 이러한 tamper-resistant virtual appliance들은 중요한 서비스들을 위해서 더욱 secure하고 안정적인 환경을 제공하고 매우 쉽게 사용할 수 있도록 하나의 패키지에 모든 필요한 소프트웨어들을 포함하게 된다. 이러한 서비스 혹은 관리성에 있어서 VT-d는 가상 머신들을 위한 memory protections와 I/O optimization을 만족시키는 client platform을 제공하도록 isolate되고 control되는 그리고 protect되는 환경을 제공하게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;strong&gt;VT-d based Virtual Appliances&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;virtual appliance는 application 그리고/혹은 서비스들을 미리정의된 집합으로써 최적화된 self-contained virtual execution environment이다. Lightweight Virtual Machine Monitor (LVMM)은 Intel VT를 사용하는 VMM으로써 두개의 수행 환경으로 client platform을 나누기 위해서 사용된다. 하나는 Windows XP와 같은 운영체제를 수행하기위한 사용자의 VM으로 video 혹은 rendering 응용들과 같은 사용자의 요구사항을 만족시키기 위한 응용, 개발과 테스트를 위한 응용, 그리고 기본적인 사무 응용들을 제공할 수 있다. 또 하나는 service partition (혹은 Server VM)으로 격리된 사용 공간에서 service OS 를 운영하게 된다. 사용자 파티션은 (예를 들어) network interface controller들을 제외한 플랫폼의 모든 장치들을 소유한다. 이때 network interface controller들은 service 파티션에 의해서 소유되는데, 이는 network traffic을 필터링하고 클라이언트 플랫폼을 위해서 다른 VM들에게 network device들을 가상화하게 된다. 서비스 파티션에서 수행되는 관리 응용들은 remote contol을 제공하여, 클라이언트 시스템을 이용해서 플랫폼의 나머지부분과 사용자 환경을 관리도록 지원한다.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;Figure 3. Client VMM 구조&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://cfs5.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvOC5qcGc=&quot; width=&quot;396&quot; height=&quot;281&quot; /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Figure 3에서 보여지는 구조는 서비스 파티션이 소유하고 있는 물리적인 network interface card 드라이버를 통한 network traffic 흐름을 보여준다. 브릿지 드라이버는 서비스 파티션 네트워크 스택과 사용자 파티션 네트워크 스택 사이에 패킷들을 라우팅해준다. 사용자 파티션에서는 가상 NIC 드라이버가 사용자 파티션으로 부터 모든 나가는 패킷들을 브릿지 드라이버로 보내고 브릿지 드라이버는 패킷들을 물리 NIC 으로 전달하게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;이러한 네트워킹 구조는 부정적인 네트워크 트래픅으로부터 고수준의 보안을 제공하게 된다. 또한 하나의 파티션과 VT 그리고 VT-d의 사용을 통해서 할당된 자원으로부터의 부정적인 공격을 격리시키는 능력을 제공하게 된다. VT-d 는 가상 가전 기반의 새로운 종류의 응용을 만들어내는 초석을 마련하게 된다. 아는 NIC 장치 모델이 사용자 파티션에 드러난 가상화 schema 보다 잘 동작한다. 이러한 scheme에서는 모든 사용자 파티션의 NIC 장치로의 접근은 intercept되고 부정적인 코드의 확산을 보호하도록 emulate된다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;LVMM과 서비스 파티션은 사용자 파티션에 사상된 DMA 버스 마스터링 장치들로부터 보호받아야만한다. 이러한 DMA-capable 장치들은 정차시스템 메모리에 접근할 수 있고, 의도적 혹은 비의도적으로 LVMM과 서비스 파티션 코드와 데이터구조를 hosting하고 있는 메모리 페이지에 접근(읽기/쓰기)을 할 수 있다. 이러한 접근들은 IT 보안에 문제점을 야기시키고, memory corruption으로 인해서 플랫폼이 쓸모없어질 수 있는데, VT-d 는 이러한 문제점을을 방지하는데 사용될 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;앞서 언급했듯이, VT-d 는 system memory 에 대해서 두가지 view (Guest Physical Address (GPA) 와 Host Physical Address(HPA))를 허용하고 있다. LVMM은 HPA view, system physical address space 를 유지하고, 사용자 그리고 서비스 파티션들은 그들의 관련된 GPA view 를 유지하게 된다. LVMM은 CPU로부터의 접근을 위해서 GPA to HPA 로 변환하기 위해서 shadow page tables 들을 유지하게 된다. 유사하게 VT-d DMA remapping 엔진들과 관련된 변환 테이블들을 이용하여 LVMM은 모든 DMA-지원 I/O 장치들을 위해서 GPA-to-HPA 사상을 유지하게 된다. Figure 4는 이러한 사용 모델을 나타내고 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;Figure 4. 클라이언트 VMM에서의 VT-d 사용 모델&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://cfs4.tistory.com/upload_control/download.blog?fhandle=YmxvZzg5NDQwQGZzNC50aXN0b3J5LmNvbTovYXR0YWNoLzAvNS5qcGc=&quot; width=&quot;480&quot; height=&quot;374&quot; /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;DMA 사상은 다음과 같이 동작한다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;모든 서비스 파티션 메모리 페이지들은 하나의 도메인에 추가되고 서비스 파티션에 사상된 DMA 장치들 (NIC들)은 오직 이러한 패이지들을 통해서만 접근이 가능하다. 
&lt;/li&gt;&lt;li&gt;모든 나머지 페이지들 (LVMM과 BIOS reserved를 제외한)은 사용자 파티션 도메인에 추가되고, 서비스 파티션에 사상된 페이지를 장치들을 제외한 모든 장치들 (예를 들어 iGFX, PCI/PCIe add-on 카드들 등)은 이러한 페이지들에 접근할 수 있다. 
&lt;/li&gt;&lt;li&gt;LVMM과 BIOS reserved 영역은 VT-d 변환 페이지 테이블에서 빠져있기 때문에 가상화된 환경에 의해서 DMA 접근들로부터 보호된다. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;이러한 device-to-domain 사상은 다음과 같은 장점을 같는다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;하나의 도메인에 사상된 I/O 장치들은 다른 도메인의 메모리에 접근할 수 없다. 예를 들어, 사용자 파티션의 PCI/PCIe add-on 카드들은 LVMM 혹은 서비스 파티션에 접근할 수 없다. 
&lt;/li&gt;&lt;li&gt;서비스 그리고 사용자 파티션의 장치 드라이버들은 GPA-to-HPA 사상을 파악하기 위해서 어떠한 변화 없이 동작한다. 이러한 변환은 장치가 GPA를 통해서 I/O 요청을 이슈할 때 VT-d 하드웨어에 의해서 투명하게 수행된다. 
&lt;/li&gt;&lt;li&gt;만약 장치가 도메인에 사상되지 않은 주소에 대해서 접근하려고 시도하는 잘못된 동작을 할 경우, VT-d 하드웨어는 fault 를 생성한다. 이러한 fault 는 LVMM에 캡춰되고 서비스 파티션에 알려진다. 서비스 파티션의 추가적인 관리 응용은 fault 의 정에 따라서 에러 메세지를 표시해주거나 platform reboot으로 초기화 등의 적절한 행동에 의한 이러한 fault 를 처리할 수 있다. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Intel VT-d requirements&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;VT-d 는 Intel Client, Workstation 그리고 일부 Server 에서부터 지원이 시작된다.&lt;/p&gt;
&lt;p&gt;하드웨어&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;VT-d 를 지원하는 chipset을 갖는 플랫폼 &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;소프트웨어&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;가상환경에서 VT-d 기능을 지원하는 VMM (혹은 Hypervisor). VMM상에서 운영되는 Guest 는 수정이 필요없음. 
&lt;/li&gt;&lt;li&gt;native OS 환경 혹은 비-가상화 환경에서는 VT-d protection 특징을 OS 에서 사용할 수 있다. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;BIOS requirements for the platform&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;VT-d 를 사용하도록 BIOS 에서 enabling 해주어야 함. BIOS는 VT-d capabilities (예를 들어 # of DMA remap engines etc)를 ACPI table 을 이용해서 VMM에게 드러내도록 해야한다. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;결론&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;VT-d 구조는 완전한 application-to-I/O 장치 데이터 전송 격리를 지원하는 가상화된 환경을 생성할 수 있는 하드웨어 메카니즘을 제공한다. 이는 더욱 가용성있고, 신뢰성있고, 보안에 강한 가상 환경을 생성을 가능하게 한다. VT-d를 이용해서 소프트웨어 개발자들은 높은 가용성을 지원하고, 높은 성능을 제공하며, 증가하는 I/O 요구에 확장성있는 I/O 자원들을 완전히 보호하는 공유를 개발할 수 있게 된다.&lt;/p&gt;
&lt;p&gt;I/O 장치 가상화를 위한 Intel 플랫폼에서의 VT-d 지원은 프로세서와 메모리 자원을 가상화하는 기존의 Intel VT 기능을 보완한다. 이를 통틀어서 VT 기술의 로드맵은 Intel 플랫폼의 가상화를 위한 완전한 하드웨어 지원을 제공하는 완벽한 솔루션을 제공한다. I/O 자원들의 가상화는 data center, enterprise, 그리고 home 에서의 새로운 사용 모델의 중요한 셋을 가능하도록 하는 중요한 step 이다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;참조&lt;/strong&gt;&lt;/p&gt;&lt;strong&gt;http://softwarecommunity.&lt;/strong&gt;Intel.com/articles/eng/1416.htm</description>
			<category>wkoh+virtualization</category>
			<category>DMA</category>
			<category>I/O</category>
			<category>virtualization</category>
			<category>VMM</category>
			<author>wkoh</author>
			<guid>http://www.v12n.info/8</guid>
			<comments>http://www.v12n.info/8#entry8comment</comments>
			<pubDate>Thu, 21 Feb 2008 17:30:38 +0900</pubDate>
		</item>
	</channel>
</rss>
