2007/06/12

volatile

volatile의 경우 어떤 의미에서는 앞에서 설명한 컴파일러의 최적화와 관계있습니다. 그 외에도 CPU 내, 외부의 캐쉬와 갈은 하드웨어적인 최적화와도 관계가 있습니다.

volatile 키워드가 가장 많이 사용되는 경우의 하나가 memory-mapped I/O인 경우입니다. 메모리의 특정 영역을 특정 장치와 연결하여 사용하는 방법입니다. 가장 흔한 예가 비디오 메모리가 되겠고, 그 이외에도 많은 장치들을 이러한 식으로 사용될 수 있습니다.

즉, 자신 엄밀하게 말한다면 컴파일러가 컴파일하고 있는 코드의 상황과는 관계 없이 바뀔 수 있는 메모리 변수가 있다면, 해당 변수에 대해 특별한 최적화를 하지 못하도록 컴파일러를 제약하는 키워드가 volatile입니다.

예를 들어, 0x0C000000 번지에 특별한 장치가 있다고 하겠습니다. 이 장치가 일종의 센서라고 하고 입력되는 센서값의 범위에 따라 다른 동작을 수행하게 프로그래밍을 아래와 같이 하였다고 하면,

int *p = 0x0C000000;

while (1) {

if (*p == 0) {
break;
} else if (*p < lower_limit) {

action 1;
} else if (*p < upper_limit) {

action 2;
}
wait 10 mili-seconds
}


똑똑한 컴파일러는 위의 코드를 아래와 아래와 같이 바꿉니다.


int *p = 0x0C000000;

register int pvar = *p;
if (pvar == 0) {

} else if (pvar < lower_limit) {

while (1) {
action 1;
wait 10 mili-seconds;
}
} else if (pvar < upper_limit) {

while (1) {
action 2;
wait 10 mili-seconds;
}
}


위와 같이 코드가 변형된다면, 프로그래머가 의도한 바와는 다른 결과가 나타나게 됩니다. 이러한 최적화를 억제하는 목적으로 volatile을 사용합니다. 컴파일러는 volatile 키워드가 선언된 변수에 대해서는 무조건 메모리에 접근하여 됩니다. 이러한 memory-mapped I/O 이외에도, 쓰레드 등으로 프로그램을 만들어서 공유변수를 한쪽에서 읽고, 한쪽에서 쓰는 경우도 해당될 수 있으며, 시스템 시간과 같이 특정 위치의 변수값이 자신과는 독립적으로 계속 변하는 경우에도 사용할 수 있습니다.

또는 CPU 내 외부의 캐쉬에 의해서도 이러한 최적화 효과가 나타날 수 있습니다. 캐쉬내에 해당 메모리 번지 값이 저장되어 읽을 때마다 같은 값이 읽히고, 또한 적을 때도 실제 메모리에 저장되지 않고 캐쉬에 임시 보관될 수 있습니다. 다른 경우는 잘 모르겠지만 MIPS의 R 시리즈 CPU에서는 (아마 2000 인가 3000 시리즈로 기억됩니다) 메모리를 두가지 방법으로 접근할 수 있습니다. 메모리 주소의 최상위 비트가 0이면 캐쉬를 거친 일반적인 접근을, 최상위 비트가 1이면 똑같은 주소의 메모리를 캐쉬를 거치지 않고 직접 접근할 수 있습니다. 당연히 이런 컴퓨터의 컴파일러에서 volatile로 선언하면 0C000000이 아니라 8C000000의 메모리를 접근하게 됩니다.



Powered by ScribeFire.

댓글 없음:

댓글 쓰기