이번 시간에서는 64비트 윈도우라는 적(?)을 만나도 자신 있게 대처할 수 있도록 윈도우 응용 프로그램 개발자 입장에서 알아야 할 64비트 윈도우의 달라진 점을 살펴보겠다. 부디 새로운 무공을 부지런히 연마해서 64비트 ‘적벽대전(赤壁大戰)’에서 반드시 승리하시길.
운영체제 : 윈도우 XP 64비트 에디션, 윈도우 2003 64비트 에디션
개발도구 : 에디터, 32/64비트 C/C++ 컴파일러
기초지식 : C/C++ 프로그래밍, 윈도우 구조 이해
응용분야 : 64비트 윈도우에서 동작하는 모든 프로그램
올해 출시되는 개인 사용자용 64비트 윈도우를 기점으로 일반 사용자에게도 64비트 세상은 가깝게 다가올 것으로 생각되며, 사용자들이 사용하는 애플리케이션을 개발하는 개발자들도 해야 할 일이 많아질 것이다. 특히 x64를 지원하는 윈도우 XP 64비트 에디션이 현재 베타가 진행 중이고 정식 발매된다면 64비트 애플리케이션이 아직 많지 않은 상황에서 사용자들의 호응을 많이 얻을 것으로 생각된다.
이전 시간에 설명했지만 x64 계열은 하위호환성을 중심으로 했기 때문에 32비트 응용 프로그램이 최적화되어 돌아갈 수 있는 환경이며 향후 64비트 애플리케이션도 충분히 지원할 수 있다. 현재 MS의 64비트 버전 발표 계획은 <표 1>과 같다.
<표 1> 64비트 윈도우 발표 계획 |
64비트 윈도우의 현재, 그리고 미래
왜 64비트 윈도우를 말하는가?
가장 즐겨하는 게임이나 회사에서 가장 많이 쓰는 사무용 소프트웨어, 개발하는데 사용하는 개발도구도 모두 32비트 윈도우에서 잘 돌아가고 있는데, 왜 64비트 윈도우가 필요한지 전혀 못 느끼게 되는 것이 사실이다. 도대체 왜 64비트 윈도우를 써야 하는 것일까? 왜 개발자들은 64비트 윈도우에서 돌아가는 프로그램을 만들어야 하는 것일까? <그림 1>을 살펴보자.
<그림 1> 64비트 윈도우의 장점 |
64비트 윈도우를 사용함으로서 얻게 되는 장점을 기술적인 관점과 사업적인 관점으로 나누어 생각해 볼 수 있는데 먼저 사업적인 측면에서 64비트 윈도우를 통해 다음과 같은 장점을 얻을 수 있다.
◆ 향상된 생산성
64비트 윈도우의 작업 성능이 32비트 윈도우에 비해 빠르다. 예를 들어 지식 기반 관련 업무를 하는 사람들이 다음 작업을 하기 위해 애플리케이션 작업이 끝나기를 기다리는 시간을 줄일 수 있고 대신 생각하는데 더 많은 시간을 할애할 수 있다
◆ 낮은 유지비용
64비트 윈도우는 더 많은 사용자와 응용 프로그램을 지원할 수 있다. 그래서 현재보다 더 적은 수의 서버만 있어도 원할하게 일을 할 수 있다. 결론적으로 기존에 비해 상대적으로 적은 비용으로도 작업에 필요한 컴퓨팅 환경을 구축할 수 있다.
◆ 새로운 애플리케이션을 만들 수 있는 기회
32비트의 장벽을 뛰어넘는 새로운 응용 프로그램을 설계할 수 있다. 예를 들어 더 쉽고 재미있는 그래픽 애플리케이션이나 게임을 만들 수도 있고 더 많은 데이터를 동시에 처리할 수 있는 애플리케이션을 만들 수도 있다.
기술적인 측면에서 눈에 띄는 것은 가상 주소 공간과 물리 메모리 크기가 기존의 32비트 윈도우에 비해 상당히 많이 늘어났다는 것과 지원하는 CPU 수가 늘어났다는 것이다. 이를 통해 기존의 32비트 처리능력 한계를 뛰어넘는 애플리케이션을 개발할 수 있다. 또 하나의 가장 큰 장점중 하나는 기존의 윈도우 개발자들이 익혀온 개발지식을 64비트 윈도우에서도 그대로 사용할 수 있다는 것이다.
32비트 윈도우와 64비트 윈도우의 메모리 및 CPU 지원에 대한 사양을 살펴보면, 32비트 윈도우에 비해 64비트 윈도우가 월등히 많은 용량의 메모리 처리 능력을 가졌음을 알 수 있다. 특히 가상 주소 공간과 물리 메모리 지원을 많이 함으로서 뒤에 자세히 언급하겠지만 가상메모리 관리자에 의한 페이징을 줄여서 일반적인 애플리케이션의 수행성능을 높일 수 있다. 자세한 비교는 <표 2>와 <표 3>을 참고하자.
<표2> 주소공간요소의 비교 |
<표 3> 물리 메모리/CPU 지원 사양 비교 |
윈도우는 어떻게 생성되는가?
이전 시간에서도 언급했듯이 앞으로 우리는 64비트와 32비트 환경을 모두 지원하기 위해 하나의 소스코드를 이용해 세 종류의 바이너리를 생성해야 한다. 64비트 윈도우 환경에서 조금 더 복잡해진 이 상황이 어쩌면 좀 억울할 수도 있다. 그렇다면 정작 윈도우를 만들어 낸 MS에서는 윈도우가 어떻게 컴파일되어지고 관리되어질까? <그림 2>를 참조하자. 잘 알려진 대로 윈도우도 C++로 작성된 소스코드를 컴파일한 바이너리일 뿐이다.
<그림 2> 윈도우 생성 모델 |
<그림 2>와 같이 윈도우도 다른 애플리케이션과 마찬가지로 하나의 소스코드로 작성되고 컴파일할 때 다른 컴파일 스위치를 이용해서 3개의 바이너리를 생성해 낸다. 기존의 32비트 윈도우가 가장 대중화된 인텔 기반의 32비트 명령어로 컴파일되었다면, 64비트 윈도우는 두 가지 종류로 컴파일된다. 하나는 인텔이 선도한 IA64 명령어로 컴파일이 되며 다른 하나는 AMD가 선도한 x64 명령어로 컴파일된다. 그렇다면 왜 하나의 소스로 3개의 바이너리를 만들어 내는 것일까?
세 개의 소스로 세 개의 바이너리를 만들어 내면 되지 않을까? 하는 물음을 가질 수 있을 것이다. 상업적인 패키지 소프트웨어를 개발하는 대부분의 회사는 통합된 소스에서 여러 플랫폼의 바이너리를 생성하는 것을 기본 원칙으로 삼고 있다. 이유는 여러 개의 소스를 관리해야 할 경우 관리부담 및 경비지출이 증가되고 같은 알고리즘이나 내용의 소스에서 버그가 발견되었을 경우 여러 곳을 수정해야 하는 번거로움이 생기기 때문이다. 결론적으로 윈도우도 하나의 소스코드로 세 종류의 윈도우를 만들어 낸다.
달라진 데이터 모델
모든 운영체제에는 데이터 모델이 존재한다. 윈도우에도 데이터 모델이 있는데 32비트 윈도우에서는 int, long, 포인터가 32비트인 ILP32 모델이었다. 그래서 현재까지 32비트 윈도우에서 개발하는 대부분의 개발자들은 데이터 모델을 신경 쓰지 않고 프로그래밍을 해왔다. 왜냐하면 포인터도 다른 대부분의 자료형도 32비트였기 때문이었다.
하지만 도스나 16비트 윈도우 프로그래밍을 해봤던 개발자라면 기억하겠지만 32비트 윈도우가 나오면서 사용하는 API나 데이터 형을 바꾸어야 했던 경험이 있을 것이다.
마찬가지로 64비트 윈도우가 나오면서 데이터 모델도 바뀌고 일부 API의 파라미터도 수정되었으며 새로운 데이터 형도 추가되었다. 다행스러운 것은 16비트에서 32비트 윈도우 애플리케이션으로 포팅해야 할 때만큼의 많은 작업은 하지 않아도 되도록 64비트 윈도우는 하위 호환성을 중시한 데이터 모델을 채택했다.
호환성을 중시한 LLP64 데이터 모델
64비트 윈도우에서는 LLP64 데이터 모델을 채택했다. LLP64 모델이란 int와 long은 32비트와 마찬가지로 32비트를 유지하고 64비트 어드레싱을 하기 위한 포인터만 64비트로 사용하는 데이터 모델이다. 잠시 유닉스와 비교해 보면 유닉스에서는 일반적으로 int와 long 그리고 포인터가 64비트인 LP64 데이터 모델을 사용한다.
장단점이 있겠지만 윈도우가 채택한 LLP64 데이터 모델의 경우 32비트 윈도우를 위해 작성된 애플리케이션 소스를 크게 고치지 않고도 64비트로 포팅할 수 있다는 장점이 있다. 그리고 하나의 소스로 32비트와 64비트 윈도우 모두에서 동작할 수 있는 애플리케이션을 작성하기도 훨씬 수월하다.
그러나 64비트 윈도우에서는 포인터의 크기가 달라졌기 때문에 상당히 주의해야 하는데 포인터가 32비트라고 생각하고 int나 long으로 형변환해서 사용할 경우 64비트 윈도우에서는 메모리 접근 오류와 같은 심각한 예외(Exception)를 발생시킬 수도 있기 때문이다.
기존의 소스를 32비트와 64비트 윈도우에서 모두 정상 동작하도록 하기 위해 가장 먼저 시도해 볼 수 있는 방법은 포인터를 사용하는 부분만 주의 깊게 코드를 재작성하는 것이고 두 번째 단계로는 다음 절에서 설명할 새로운 데이터 타입을 이용해 포인터를 재정의하는 방법이 있다. 시간이 허락한다면 당연히 새로운 데이터 타입을 이용해 포인터 사용 부분을 수정하는 것이 좋겠다. 32비트 윈도우 애플리케이션을 64비트용으로 포팅하는 방법에 대해서는 다음에 더 자세히 설명하겠다. 운영체제별 데이터 모델은 <표 4>를 참고하자.
<표 4> 운영체제별 데이터 모델 |
새로운 데이터 타입
64비트 윈도우에서는 32비트 윈도우와 64비트 윈도우에서 모두 정상 동작하는 소스를 작성하기 쉽게 하기 위해 세 가지 종류의 새로운 데이터 형을 정의했다. 첫 번째는 32비트나 64비트 윈도우에 상관없이 고정된 크기를 갖는 데이터 형이다. 윈도우가 채택한 LLP64 모델의 경우 int나 long은 모두 32비트를 유지하기 때문에 새로운 데이터 형을 사용하지 않아도 32비트와 64비트 윈도우에서 동작할 수 있는 소스를 작성할 수 있지만 할 수 있다면 새롭게 추가된 크기가 고정된 일반 데이터 형을 사용하는 것이 좋다. 데이터 형 이름에 지정된 비트 수를 통해 소스의 가독성이 높아지고 버그 발생의 가능성을 줄이기 때문이다(<표 5> 참고).
<표 5> 크기가 고정된 일반 데이터 형 (Fixed Precision) |
두 번째로 새롭게 추가되는 형은 윈도우에 따른 크기가 다른 포인터 형이다. 이 형들은 32비트 윈도우에서는 32비트 포인터이며 64비트 윈도우에서는 64비트 포인터이다. 64비트 윈도우에서 포인터 크기만 64비트로 바뀐 것을 생각한다면 이 포인터 형들을 잘 사용해야 한다. 소스 상에서 포인터를 사용하는 부분을 새롭게 추가된 이 포인터 형들로 사용한다면 32와 64비트 윈도우에서 모두 원활하게 동작하는 애플리케이션을 개발하기 훨씬 수월하다(<표 6> 참고).
<표 6> 윈도우에 따라 크기가 다른 포인터 형 (Pointer Precision) |
마지막으로 새롭게 추가된 데이터 타입은 크기가 분명하게 고정된 포인터 형이다. 한 가지 주의할 것은 64비트 윈도우에서는 POINTER_32를 이용해 코드를 작성해도 운영체제는 64비트 포인터를 생성하고 32비트 부분만 유효한 포인터로 사용한다는 점이다. 크기가 고정된 포인터 형에 대한 설명은 <표 7>을 참고하자.
<표 7> 크기가 고정된 포인터 형 (Specific Pointer-Precision) |
이 새로운 데이터 형들은 플랫폼 SDK(Software Development Kit) 최신 버전에 포함되어 있는 basetsd.h에 정의되어 있다. 새로운 데이터 형들을 사용하게 되면 포인터 사용과 형변환 그리고 데이터 정의를 안전하게 할 수 있으므로 새로 작성하는 코드라면 플랫폼에 상관없이 새로운 데이터 형을 사용하는 것이 좋다.
데이터를 다루기 쉽게 해주는 함수
64비트 윈도우에서는 32비트 윈도우와 64비트 윈도우 모두를 지원해야 하는 소스를 작성해야 하고 데이터형 간의 형변환 등을 자주 사용해야 할 때 이런 작업을 쉽고 안전하게 할 수 있도록 도와주는 함수들이 추가되었다. 이 함수들도 역시 basetsd.h에 정의되어 있다. 이 함수들의 리스트는 <표 8>을 참고하자.
<표 8> 데이터를 다루기 쉽게 해주는 함수 |
무한 자원을 목표로 - 64비트 주소공간
64비트 윈도우는 32비트 윈도우에 비해 훨씬 큰 크기의 가상 메모리를 지원한다. 정확하게 말하자면 32비트 윈도우가 4GB의 가상 메모리를 지원하는데 비해 64비트 윈도우는 16TB까지의 가상 메모리를 지원한다고 한다. 그리고 64비트 윈도우는 32비트 윈도우에 비해 훨씬 큰 크기의 물리 메모리(Physical Memory)를 사용할 수 있기 때문에 완전하게 64비트로 개발된 애플리케이션은 다음과 같은 장점이 있다.
◆ 더 많은 사용자 지원이 가능하다
여러 사용자의 로그온 세션에 동작할 수 있는 윈도우 NT 4.0 터미널 서비스 에디션이 발표된 후에 애플리케이션 개발자가 신경 써야 할 사항들이 늘어나게 되었다. 윈도우 XP나 윈도우 2003의 경우에도 마찬가지로 하나의 애플리케이션에 대해 여러 사용자 계정으로 수행 가능하게 되는데 이런 환경에서는 더 많은 메모리를 사용할 수밖에 없다. 64비트 윈도우는 32비트 윈도우에 비해 더 큰 메모리를 지원하기 때문에 더 많은 사용자 작업을 지원할 수 있다.
◆ 더 뛰어난 수행 성능을 낼 수 있다
64비트 윈도우는 물리 메모리 주소 공간이 32비트에 비해 월등히 커서 동시에 더 많은 수의 애플리케이션이 물리 메모리에서 동시에 동작할 수 있다. 일반적인 32비트 애플리케이션이 여러 개 수행될 경우 제한된 물리 메모리상에서 동작해야 하므로 어떤 애플리케이션에서 사용하는 메모리는 가상 메모리 관리자 정책에 의해 하드디스크로 페이지를 스왑하는 오버헤드가 발생하게 되는데 64비트 애플리케이션은 이 오버헤드를 최소화할 수 있기 때문에 더 뛰어난 성능을 낼 수 있다.
◆ 더 많은 데이터를 저장하고 사용할 수 있다
기존의 32비트 윈도우 기반의 데이터베이스에서 대부분의 데이터는 디스크에 위치해 있었고 데이터를 사용하려면 디스크 접근이 필요했기 때문에 속도가 낮을 수밖에 없었다. 64비트 윈도우는 더 많은 양의 데이터를 물리 메모리에 저장해 놓을 수 있어서 훨씬 빠르게 데이터를 사용할 수 있고 더 많은 양의 데이터를 저장할 수 있다.
◆ 많은 양의 데이터를 쉽고 신뢰성 있게 사용할 수 있다
과학이나 재무에 관련된 모델링 애플리케이션이나 동영상 편집 소프트웨어가 64비트 윈도우에서 동작한다면 32비트 윈도우에서 힘들었던 작업을 훨씬 쉽고 신뢰성 있게 처리할 수 있다.
가상주소공간의 변화
32비트 윈도우에서는 사용자 모드 주소공간에 2GB를 할당할 수 있었고 커널 모드 주소공간에 2GB를 할당할 수 있었다. 32비트 윈도우가 처음 등장할 때만 해도 2GB 윈도우가 충분한 주소공간이었지만 데이터베이스 같은 애플리케이션에서는 비좁은 공간이 되어 버렸다. 그래서 32비트 윈도우에서는 /3gb 스위치로 부팅하면 사용자 모드 주소 공간을 3GB까지 할당할 수 있게 하고 애플리케이션 작성 시에는 윈도우 2000 이상에서 사용할 수 있는 AWE( Address Window Extension) 기법을 사용해 4GB 이상의 주소공간을 사용할 수 있게 했다.
또한 <그림 3>과 같이 32비트 윈도우는 최대 4GB(일부 윈도우 서버 에디션은 최대 64GB)의 물리 메모리만을 지원하고 프로세스 간에 이 영역을 공유해서 사용해야 했기 때문에 시스템상의 물리 메모리보다 더 많은 양의 메모리 페이지를 프로세스들이 사용할 경우 잦은 디스크 스왑을 발생시켜 프로세스 수행 성능저하의 원인이 되었다.
<그림 3> 32비트 윈도우에서의 메모리 사용 예 |
64비트 윈도우는 32비트 윈도우에 비해 훨씬 큰 크기의 주소 공간을 제공하는데 64비트 윈도우에서 프로세스의 사용자 모드 주소 공간은 기본적으로 8TB이며 커널 모드 주소공간도 8TB이다. 32비트 윈도우의 사용자 모드 기본 주소공간이 2GB이므로 4,096배에 해당하는 엄청난 공간이다.
그리고 <그림 4>와 같이 64비트 윈도우는 최대 32GB(일부 윈도우 서버 에디션은 최대 1TB)의 물리 메모리를 지원하고 프로세스 간에 이 영역을 공유하지 않고도 사용할 수 있을 만큼 크기 때문에 메모리 페이지의 디스크 스왑이 많이 발생하지 않을 수 있고 프로세스의 수행 성능이 높아질 수 있다.
<그림 4> 64비트 윈도우에서의 메모리 사용 예 |
그렇다면 64비트 프로세스라도 기존의 32비트 프로세스처럼 2GB만 사용자 모드 주소공간으로 사용할 수도 있을까? 답은 ‘그렇다’이다. 예를 들어 2GB 주소공간이면 충분한 애플리케이션이거나 소스코드 내에서 너무 많은 포인터 연산과 포인터와 정수형 간에 형변환이 발생해서 포인터 사용이 안전하지 않을 경우에는 기존의 32비트 소스코드를 크게 수정하지 않고 64비트 프로세스로 사용할 수 있는 방법이 있다.
이 방법은 컴파일 시 특수한 스위치인 /LARGEADDRESSAWARE:NO를 사용하게 되는데 이 옵션을 이용해 컴파일된 64비트 프로세스는 시스템이 메모리 할당을 2GB 안에서만 하게 되고 64비트 포인터 중 32비트만 유효한 상태가 되기 때문에 포인터 사용이 안전해진다. 그러나 주의할 점은 64비트 프로세스에서 사용하게 되는 다른 DLL들이 64비트 주소공간 모두를 의미 있게 사용하게 될 경우 심각한 오류를 발생시킬 수도 있다. 다른 DLL들까지 2GB 안에서만 주소공간을 사용하도록 강제하는 것이 아니기 때문이다.
결국 64비트 프로세스에서 기존의 32비트 프로세스처럼 2GB만 주소공간으로 사용하려면 프로세스 안에서 사용되는 모든 모듈을 /LARGEADDRESSAWARE:NO 스위치로 컴파일해야 하지만 현실적으로는 어려움이 많으며 빠른 시일 안에 64비트 윈도우를 위한 완벽한 소스코드를 작성하는 것이 좋다.
달라진 서브시스템 지원
32비트 윈도우와 64비트 윈도우에는 알아둬야 할 중요한 차이점이 있는데 64비트 윈도우에는 32비트에 있던 서브시스템 중 지원하지 않는 것도 있고 추가된 것도 있다는 점이다. 삭제된 서브시스템은 POSIX와 OS/2 서브시스템이며 추가된 서브시스템은 이전 글에서 언급했던 WOW64이다. 하위 호환성을 중시하는 MS임에도 이 서브시스템들을 지원하지 않는 이유는 실제로 POSIX나 OS/2 서브시스템을 사용하는 응용 사례가 적어서인 것으로 보인다. 알다시피 WOW64는 64비트 윈도우에서 32비트 애플리케이션의 구동을 위해서 탑재되었다.
Win64 API? Win32 API?
지난 1992년 7월 MS는 32비트 윈도우 NT를 위한 차세대 API인 Win32 API를 발표했다. Win32 API는 10년이 훌쩍 지난 지금까지 윈도우 개발자들의 기본적인 무공으로서 사랑받고 있다. 그렇다면 64비트 윈도우에서는 어떤 API를 사용하고 있을까? Win64 API는 존재하는 것일까?
64비트 윈도우가 실제로 출시되기 이전에는 개발자들은 당연히 64비트 윈도우가 등장하면 Win64 API도 같이 발표될 줄 알았다. 하지만 앞서 데이터 모델을 LLP64 모델로 채택한데서 살펴볼 수 있듯이 MS는 호환성을 중시했다. 그래서 64비트 윈도우에서 Win64 API는 존재하지 않고 Win32 API를 사용한다.
정확하게 말하자면 Win32 API와 거의 동일한 형태의 API를 64비트 윈도우의 기본 API로 채택했다. Win32 API와 거의 동일한 형태의 API를 채택함으로써 얻는 장점은 윈도우 개발자들이 새로운 API를 익혀야 할 필요가 없이 친숙한 API를 사용할 수 있고 기존의 32비트 소스코드를 많이 수정할 필요 없이 64비트로 포팅 가능하며 32비트와 64비트 윈도우에서 모두 동작하는 하나의 소스코드를 작성하기에도 손쉽기 때문이다.
그렇다고 모든 API가 동일하지는 않고 약간의 차이점도 있다. 예를 들어 32비트와 64비트 윈도우에서 모두 동작하는 소스를 작성하기 위해 <표 9>의 이전 API 대신 <표 9>의 권장 API를 사용하기를 요구하고 있다. 각 API의 자세한 사용법은 컴퓨터에 설치된 최신판 MSDN 또는 인터넷 MSDN 사이트인 http://msdn.microsoft.com/을 참조하기 바란다.
<표 9> 64비트 윈도우에서 사용하기 권장하는 API |
이제는 지켜야 할 약속 - 바이트 정렬
기존 32비트 윈도우에서 동작하는 애플리케이션을 작성할 때 많은 개발자들이 바이트 정렬(Alignment)에 대해 그다지 신경을 쓰지 않고 작성했다. 32비트 CPU의 경우 4바이트 단위로 데이터를 처리하기 때문에 4바이트로 정렬되었을 경우에 가장 효율적이었지만 설사 정렬이 되어 있지 않다고 해도 CPU는 다음 사이클에 데이터를 획득해서 처리함으로서 정렬에 관련된 예외를 발생시키지 않았다.
그러나 64비트 윈도우에서는 바이트 정렬이 상당히 중요한 문제인데 특히 IA64 계열의 시스템은 바이트 정렬이 이루어지지 않았을 경우 정렬에 관련된 예외를 발생시킨다. 만약 이 예외가 커널 모드에서 발생한다면 심각한 BSOD(Blue Screen Of Death)가 발생하게 되므로 64비트 윈도우의 커널 모드에서 WOW64와 같은 에뮬레이션 모드도 없기 때문에 모든 코드를 64비트로 포팅해야 하는 드라이버 개발자들은 특히 주의해야 한다.
x64 계열의 시스템은 CPU가 기존의 32비트 CPU와 같이 바이트 정렬 예외를 자동으로 처리한다. 조금 더 자세히 설명하면 64비트 윈도우에서 바이트가 정렬되어서 처리되지 않을 경우 EXCEPTION_DATATYPE_MISALIGNMENT예외가 발생한다. 물론 프레임 기반의 SEH(Structured Exception Handling) 예외 처리기가 해당 쓰레드 컨텍스트에 존재하고 EXCEPTION_DATATYPE_MISALIGNMENT 예외 발생을 처리한다면 좋을 것이다.
그러나 일반적으로 프레임 기반의 예외 처리기가 존재한다고 기대하기 힘들다. 그래서 SEM_NOALIGNMENTFAULTEXCEPT를 파라미터로 넘겨 SetErrorMode 함수를 호출하면 운영체제의 정렬실패 처리기가 켜지게 되고 사용자 모드의 EXCEPTION_DATATYPE_MISALIGNMENT 예외는 자동으로 처리하게 된다. 주의해야 할 점은 시스템의 정렬 실패 처리기가 켜져 있고 바이트 정렬이 되어 있지 않아서 바이트 정렬을 자동으로 처리한다면 프로세스의 성능이 꽤 저하될 수도 있다는 것이다.
적절한 변수 배치의 중요성
이 밖에도 구조체의 아이템들을 잘못 배치할 경우 <그림 5>와 같이 32비트 윈도우에서는 20바이트만 사용하게 되지만 64비트 윈도우에서는 40바이트를 사용하게 된다.
<그림 5> 32비트 윈도우와 64비트 윈도우의 기본 얼라인먼트 |
<그림 5>의 구조체를 조금만 다시 배치하면 훨씬 효율적인 메모리 사용을 할 수 있게 되는데 <그림 6>을 참고해 보면 패팅 바이트가 붙어야만 하는 char s와 int i를 같이 배치하고 8바이트를 차지하는 포인터들을 앞에 배치해서 8바이트 가량을 줄일 수 있음을 알 수 있다.
<그림 6> 잘못 배치된 변수에 의한 메모리 낭비 최적화 |
결론적으로 바이트 정렬을 하지 않은 소스코드를 작성하면 일부 64비트 시스템에서는 심각한 오류를 발생시킬 수 있으며 오류가 발생하지 않게 자동 처리한다고 해도 성능이 많이 낮아질 것이다. 또한 64비트 윈도우 애플리케이션에서 8바이트 미만을 차지하는 변수들을 적절히 배치하지 않으면 메모리 낭비를 많이 할 수 있다. 그러므로 이제부터 작성하는 소스는 반드시 바이트 정렬과 변수들의 적절한 배치를 신경 써서 작성해야 할 것이다. 바이트 정렬에 관련된 코딩 기법은 다음 연재에서 자세히 설명하겠다.
변화의 근본을 이해하자
필자는 최근 세상의 모든 일에는 원칙과 기본이 가장 중요하다는 것을 절실히 깨닫고 모든 일에 기본을 충실히 하고 원칙을 준수하고자 노력중이다. 새로운 문제를 이해해야 할 때 기본이 되는 것은 근본을 먼저 파악하는 것이다. 그런 관점에서 살펴보면 많은 부연 설명보다는 사실 가장 중요한 것은 몇 가지의 핵심사항을 이해하는 것이다.
그래서 64비트 환경이 출현한 배경과 64비트 CPU의 두 가지 갈래, 그리고 64비트 윈도우가 채택한 데이터 모델 및 메모리 관리 방법의 변화의 근본을 이해한다면 64비트라는 새로운 적 앞에서도 당당히 맞설 수 있을 것이다.
결론적으로 64비트 윈도우가 가고자 하는 방향은 기존의 32비트와 64비트 모두를 원활하게 지원하고 하나의 소스코드를 이용해 32비트와 64비트 애플리케이션 개발을 할 수 있으며 향후 기업 환경이나 엔터프라이즈 환경에 맞는 진정한 64비트 애플리케이션을 개발하기 쉬운 환경을 제공하는 것을 목표로 하고 있다. 다음 글에서는 64비트 개발 환경과 32비트 코드의 64비트 포팅 방법 및 플랫폼에 의존적이지 않은 하나의 통합된 소스코드 작성기술에 대해 살펴보겠다.@
* 이 기사는 ZDNet Korea의 제휴매체인 마이크로소프트웨어에 게재된 내용입니다.
출처 : http://www.zdnet.co.kr/techupdate/lecture/os/0,39024998,39135588,00.htm