volatile 키워드는 간단히 '코드 최적화를 막아주는 키워드'라고 설명할 수 있습니다. 즉 컴파일러의 최적화와 관련된 키워드이고 CPU 내/외부 캐시와 같은 하드웨어 최적화와도 관계가 있습니다. 지금처럼 임베디드 기반 프로그래밍이 보편화 되지 않았던 시절에는 volatile 키워드의 활용 빈도가 매우 낮았으나, 최근 임베디드 시스템이나 멀티 스레드를 고려한 프로그램이 늘어 가면서 volatile 키워드의 사용이 많아 지고 있습니다.

volatile 키워드는 주로 memory-maped I/O에서 사용됩니다. 임베디드 시스템에서는 MCU의 각종 레지스터가 메모리에 매핑되어 있는 경우가 많고 프로그램은 매핑된 메모리 주소에 값을 반복적으로 쓰게 되는데 이때 volatile 키워드가 사용됩니다. 다음의 코드로 volatile 키워드가 어떻게 동작하는지 살펴봅시다.

 

unsigned int *uart = 0x40700000;
*uart = 0x00080001;
*uart = 0x00080002;
*uart = 0x00080003;
*uart = 0x00080004;
*uart = 0x00080005;


위 코드를 보면 다섯 번째 메모리 쓰기가 모두 0x4070000번지에 행해집니다. 일반적인 상황에서 위 코드를 수행하고 나면 0x40700000 번지에는 가장 마지막 값인 0x00080005만 남게 될 것입니다. 따라서 똑똑한 컴파일러는 위 코드를 아래 코드처럼 최적화합니다.

 

unsigned int *uart = 0x40700000;
*uart = 0x00080005;

 

어차피 변수에는 가장 마지막 값만 남으므로 이렇게 고치는 것입니다. 일반적인 프로르매에서라면 아무런 문제 없이 동작하고 속도도 빨라집니다. 하지만 이 코드가 MMIO(Memory-Maped I/O) 상황에서 사용된다면 이것은 분명히 잘모된 최적화입니다. 각각의 메모리 쓰기 작업이 하드웨어에 특정한 작업을 명령하기 때문에 저렇게 최적화를 해 버리면 하드웨어는 오작동을 하게 됩니다. 그러므로 컴파일러에 최적화를 하지 말라는 '지시'를 내려야 합니다. 이러한 지시는 내리는 키워드가 바로 volatile입니다.

 

volatile unsigned int *uart = 0x40700000;
*uart = 0x00080001;
*uart = 0x00080002;
*uart = 0x00080003;
*uart = 0x00080004;
*uart = 0x00080005;

 

위와 같이 uart변수를 volatile로 선언하면 컴파일러는 uart변수에 최적화를 하지 않고모든 읽기 쓰기 작업을 메모리에서 직접하게 됩니다. 위 코드의 쓰기 작업 뿐만 아니라 읽기 작업도 마찬가지 입니다.

 

unsigned int *uart = 0x40700000;
char ch;
int i;
for(i = 0;i < 5;i++)ch = *uart;

 

위와 같은 코드 역시 최적화를 하면 *uart의 값을 한번만 읽어서 캐시에 저장한 다음 이것을 반복해서 사용합니다. 하지만 아래 코드처럼 uart 변수가 volatile로 선언되면 루프안에서 uart변수를 요구할 때마다 매번 메모리에서 값을 가져오기 때문에 그때 그때 변경되는 값을 읽을 수 있습니다.


volatile unsigned int *uart = 0x40700000;
char ch;
int i;
for(i = 0;i < 5;i++)ch = *uart;

 

---------------



'게임개발공부 > 무작정퍼오기' 카테고리의 다른 글

함수객체  (0) 2013.12.29
DLL만 로딩해도 컴퓨터가 뻗는경우.  (0) 2013.12.21
extern "C" 이건 뭔가? (퍼온글)  (0) 2013.12.21
dll의 기본. (퍼온글)  (0) 2013.12.21
컨테이너 종류 복습  (0) 2013.12.21
Posted by JJOREG