각 바이트는 고유의 물리 주소(PA)를 가지고 있다. CPU가 메모리에 접근하는 가장 자연스러운 방법은 물리 주소를 사용하는 것이고, 이를 물리 주소 방식이라고 한다. CPU가 로드 인스트럭션을 수행할 때 유효 물리 주소를 생성하고, 이것을 메모리 버스를 거쳐 메인 메모리에 전달한다. 메인 메모리리는 전달받은 물리주소에서 시작해 특정 바이트만큼 선입하고, 이것을 CPU를 돌려주고, 레지스터에 다시 저장한다.
CPU는 가상주소지정으로 가상주소(VA)를 생성하여 메인 메모리에 접근하며, 이것은 메모리에 보내지기 전에 적절한 물리 주소로 변경된다. 가상 주소를 물리 주소로 변환하는 과정을 주소 번역이라고 한다. CPU칩 내에 메모리관리유닛(MMU)이라는 전용 하드웨어는 메인 메모리에 저장된참조 테이블을 사용해서 실행중에 가상 주소를 변역한다. 이 테이블의 내용은 운영체제가 관리한다.
프로세스의 페이지 정보를 저장하고 있는 테이블 → PTE
메인 메모리에 저장되어 있고 MMU가 가상 주소를 물리 주소로 번역할 때 읽는다.
페이지 테이블은 페이지 테이블 엔트리(PTE)의 배열이다. 각 페이지는 페이지 테이블 내 지정된 오프셋에 PTE를 가지고, PTE는 한 개의 유효(valid)비트와 나머지 n 비트의 주소 필드로 구성되어 있다.
가상 주소가 MMU를 거쳐 번역된 물리 주소 공간에 데이터가 적재되어있는 경우를 말한다.
적중과 반대로 가상 주소에서 번역을 통해 나온 물리 주소 공간에 데이터가 없어서 페이지 오류 예외가 발생된 경우를 말한다. Page Fault가 발생하면 프로세스의 명령어 수행을 중지(Trap)가 발생되고, 디스크에서 해당 페이지를 로딩한 후에 명령어를 재시작해야하나.
선행처리 지시문에 인수로 함수의 정의를 전달함으로서, 함수처럼 동작하는 매크로를 만들 수 있다.
함수같은 매크로 또는 매크로 함수라고 한다.
#include <stdio.h>
#define SUB(X, Y) X-Y
#define PRT(X) print("계산 결과는 %d입니다.\n", X)
int main(void)
{
int result;
int num_1 = 15, num_2 = 7;
result = SUB(num_1, num_2);
PRT(result);
return 0;
}
매크로 함수는 일반 함수와 달리 순수 치환만 해주기 때문에 일반 함수와 완전 똑같이 동작하지 않는다.
#include <stdio.h>
#define SQR(X) X*X
#define PRT(X) printf("계산 결과는 %d입니다.\n", X)
int main(void)
{
int result;
int x = 5;
result = SQR(x);
PRT(result);
result = SQR(x+3);
PRT(result);
return 0;
}
#include <stdio.h>
#define PRT(X) printf("계산 결과는 %d입니다.\n", X)
int SQR(int x) {
return x * x;
}
int main(void)
{
int result;
int x = 5;
result = SQR(x);
PRT(result);
result = SQR(x+3);
PRT(result);
return 0;
}
SQR(x+3)의 연산 과정을 비교해보면, 일반 함수는 인자의 값을 먼저 계산, 그 다음 함수를 거쳐 연산이 완료된다.
하지만 매크로 함수의 경우 순수 치환만 제공하기 때문에 x + 3 x + 3이 계산되는데, 사칙연산 규칙에 따라 3x가 먼저 계산되기 때문에 두 연산 결과가 다르게 적용된다.
일반 함수는 프로그램이 실행중일 때 인자를 전달받지만, 매크로 함수는 컴파일 과정에서 치환이 완료된 다음에 실행되기 때문에 두 동작방식이 다르다.
만약 이런 연산 오류를 줄이려면 매크로 함수에 괄호를 적절하게 활용하면 된다.
#include <stdio.h>
#define SQR(X) (X) * (X)
#define PRT(X) printf("계산 결과는 %d입니다.\n", X)
int main(void)
{
int result;
int x = 5;
result = SQR(x);
PRT(result);
result = SQR(x+3);
// result = (x + 3) * (x + 3)
PRT(result);
return 0;
}