응용 프로그램의 C 언어 개발에 휘발성 키워드

휘발성 물질

1.volatile 역할

휘발성 의도 컴파일러 때문에 일반적으로 액세스 메모리 최적화를 줄이기 위해,하지만 더러운 데이터가 읽을 수있는 "변수"로, 훨씬 빠른 메모리 액세스 레지스터 액세스 유닛보다 때문이다. 휘발성 선언이 변수 값을 요구하는 경우, 시스템 메모리는 명령을 방금 읽은 데이터 그로부터을 이전 한 경우에도 그것에서 데이터를 다시 읽어 항상. 컴파일러가 선언 될 것입니다 당신이 valatile를 사용하지 않는 경우, 정확하게, 그것은 특정 주소로 안정적인 액세스를 제공 할 수있는 변수 선언, 변수 액세스 코드의 컴파일러는 더 이상 최적화 될이 키워드 만남,이다 문을 최적화 할 수 있습니다.

간단한 풋가있다 : 휘발성 키워드가 피할 실수에 최적화 된 컴파일되지 않는 변수 운영과 관련된 변수는 언제든지 변경 될 수 있습니다 변수 휘발성 선언에 의해 표현 컴파일러의 결과에 영향을 미칠
1> 컴파일러는 어떤 최적화를 할 수없는 이야기
프로그램 외부에서 정의 2>를 사용하여 휘발성 변수마다 메모리로부터 판독되어야 바뀌지 만 백업 캐시 또는 레지스터를 재사용 할 수 없다.

2. 주요 시나리오

1> 변수는 일상적인 변화는 휘발성 추가 할 필요가 인터럽트 서비스에서 다른 프로그램에 의해 감지;
static int i=0;
int main(void)
{
    while (1){
  if (i) dosomething();
 }
}
/* Interrupt service routine. */
void ISR_2(void)
{
     i=1;
}

계획된 프로그램 컴파일러는 메인 함수 내부에서 나 수정 여부를 판단하기 때문에, 그러나 기능 해봐요 메인 함수 호출 발생 인터럽트 ISR_2이며, 따라서 레지스터의 동작 전으로부터 판독 한 번만 수행 될 수 있고, 각각의 초 만 해봐요 결과, 레지스터 내부의 "내가 복사"의 사용이 호출되지 않을 경우 확인합니다. 변수 수정 플러스 휘발성 경우, 컴파일러는 판독이 (양의 실행)에 최적화되지 않음을 보장하기 위해 변수를 기록한다. 이 예에서는 이와 같이 설명한다.

작업 공유 2> 멀티 태스킹 환경은 기호 휘발성를 추가해야합니다입니다

두 스레드가 특정 변수에 사용되는 상기 변수의 값이 변경 될 때, 그것은 휘발성 선언되어야 주요 역할은 CPU의 레지스터에 메모리로부터 변수를 최적화 컴파일러를 방지하는 것이다. 변수가 레지스터에로드되는 경우, 두 개의 스레드 프로그램의 실행에서 오류가 발생할 수있는 메모리에 사용 변수 변수 레지스터에 가능성이있다. 휘발성 컴파일러 변수의 동작은 실제로 메모리에서 제거해야마다, 레지스터 대신하여 이미 존재하는 값 것일까

volatile BOOL bStop = FALSE; //bStop 为共享全局变量
(1) 在一个线程中:  
  while( !bStop ) { ... }  
  bStop = FALSE;  
  return;    

(2) 在另外一个线程中,要终止上面的线程循环:  
  bStop = TRUE;  
  while( bStop ); 

bStop가 레지스터로 읽어 되었기 때문에 당신이 언급 휘발성 bStop를 사용하지 않는 경우, 위의를 종료 할 스레드가 대기하는 것은,이주기가 무한 루프 될 것 레지스터 값 bStop 휘발성, 프로그램 실행과 함께, FALSE가되지 않습니다 때마다 메모리에서 bStop의 값을 읽을 때, 그것은 죽음의 사이클을하지 않습니다.

3> 일반적으로 메모리는 각각의 판독 다른 의미를 가질 수 있기 때문에 레지스터는 하드웨어 voliate 추가 매핑.
int *output = (unsigned int *)0xff800000;//定义一个IO端口;
int init(void)
{
      int i;
      for(i=0;i< 10;i++){
         *output = i;
        }
}

결국이 $ 9 바로 출력 포인터이기 때문에 컴파일러 최적화 후, 오랜 시간 생각 넌센스에 대한 순환의 컴파일러 앞, 최종 결과에 영향은, 당신은 최종 결과 컴파일 된 코드를 컴파일하는 컴파일러에 해당됩니다 제공 :

int init(void)
{
     *output = 9;
}

이 외부 장치가 할당 위의 코드와 같은 순서로 초기화해야합니다 처리하는 경우, 분명히 최적화 과정은 자신의 목표를 달성 할 수 없다. 반면에 당신은 아마 한 번만 주소로 코드를 읽어 포트가 반복적으로 컴파일러 최적화, 결과는 동일에 적혀 있지만, 반복 읽기 동작을 작동하지 않는 경우. 그러나 코드의 관점에서 아무런 문제가 없다. 변수가 불안정한 것을 휘발성의 사용에 관하여이 때 경험이 시간 변수를 최적화하지 컴파일러를 알려줍니다.

예를 들면 :

volatile int *output=(volatile unsigned int *)0xff800000;//定义一个I/O端口

3. 일부 문제

1> 매개 변수가 될 수 있습니다 중 하나 CONST는 휘발성이 될 수 있습니까?
가능한 만 상태 레지스터를 읽을 등. 이 예기치 않게 변경 될 수 있기 때문에 휘발성이다. 프로그램을 수정하지해야하기 때문에이 const로한다.
2> 포인터는 휘발성이 될 수 있습니까?
수 때 인터럽트 서비스 루틴의 수정 버퍼에 대한 포인터.

4.volatile 자연 :

1> 컴파일러 최적화
변수를 읽을 때이 글은, 상기 액세스 속도를 향상시키기 위해, 컴파일러 최적화 변수는 제 1 레지스터로 판독 될 수 시간 후에 다음 변수 값을 취 직접 레지스터 값에서 상기 변수 값은이 글의 변화도의 일관성 변수 레지스터에 새로운 값을 복사한다.

변수가 다른 스레드와 다른 값으로 인해 변경되는 경우, 레지스터의 값은 변수 값 초래 따라 변경되지 않고, 실제 값은 응용 일관성을 읽었다.
값의 결과 값을 변경 원래 변수의 값이 변경되지 인해 다른 스레드 등이 등록하고 애플리케이션 변수의 실제 값이 일치 읽으면.

2> 휘발성는 "원시 메모리 주소에 직접 액세스"더 적절하게 해석되어야하며, 이러한 해석 "휘발성"그것은 약간 오해의 소지가 있었다.

5. 다음과 같은 기능에 어떤 문제가 :

int square(volatile int *ptr)
{
 return *ptr * *ptr;
}

이 프로그램의 목적은 포인터 반환하는 것입니다 광장의 값으로 PTR 점을, 그러나 때문에 PTR 매개 변수 포인트 휘발성으로, 컴파일러는 다음과 유사한 코드를 생성합니다 :

int square(volatile int *ptr)
{
 int a,b;
 a = *ptr;
 b = *ptr;
 return a * b;
}

* 표시의 PTR의 값이 갑자기 따라서 변경 될 수 있기 때문에 B는 상이 할 수있다. 그 결과,이 코드는 제곱 값을 기대하는 것보다 반환 할 수 있습니다! 다음과 같이 올바른 코드는 다음과 같습니다

long square(volatile int *ptr)
{
 int a;
 a = *ptr;
 return a * a;
}

참고 : 휘발성의 빈번한 사용은 코드 크기를 늘리고 성능이 저하 될 가능성이 높습니다, 따라서 합리적인 사용 휘발성.





추천

출처www.cnblogs.com/DaLinY/p/656bed417d38156a9255b53b0696f3d7.html