반응형

이 글은  컴퓨터 밑바닥의 비밀 chapter 3.4의 내용을 읽고 요약한 글입니다. 

 

3.4.1 힙 영역이 필요한 이유

  • 프로그래머가 수명 주기를 포함하여 완전히 직접 제어할 수 있는 매우 큰 메모리 영역
  • 어떻게 힙 영역에 메모리를 할당하고 해제하는지 구현

3.4.2 malloc 메모리 할당자 직접 구현하기

  • 메모리 할당자는 적절한 크기의 메모리 영역을 제공하기만 하고 무엇을 저장할지 신경쓰지 않음
    • integer, floating number 등 신경쓰지 않고 단순한 바이트의 연속에 지나지 않음
    • 커다란 배열 형태

힙 영역 위에서 두가지 문제 해결

  1. malloc 함수 구현
    1. 메모리 영역을 요쳥하면 힙 영역에 가능한 메모리 영역 찾아 요청자에게 반환
  2. free 함수 구현
    1. 메모리 영역의 사용이 완료되었을 때 메모리 영역을 반환하는 방법 구현

 

3.4.3 주차장에서 메모리 관리까지

주차장에 비유하여 표현하면 2가지 목표를 만족시켜야 함

  1. 주차할 위치를 빠르게 찾음. 요청된 크기를 만족하는 여유메모리를 빨리 찾음
  2. 주차장 사용률 극대화. 메모리를 요청할 때 가능한 많은 메모리 할당 요청을 만족시켜야 함

4가지 문제점

  1. 메모리 조각의 할당 상태 추적
  2. 단일 메모리 할당 요청의 요구사항을 만족하는 사용 가능한 메모리 조작이 매우 많을 때 할당 기준
    1. 6바이트 요청했는데 여유 메모리 공간이 16, 32, 8 바이트 일때
  3. 16바이트 메모리를 요청해야 하는데 여유 메모리 조각의 크기가 32바이트라서 16바이트가 남는 경우
  4. 사용 반환된 메모리를 어떻게 처리해야 하나?

3.4.4 여유 메모리 조각 관리하기

  • 위의 4가지 문제점들 중 1번 해결을 위한 방법으로 linked list로 메모리 사용정보를 기록하는 방식

2가지 정보를 기록

  • 메모리 조각의 크기를 기록한 숫자 - header라고 하며 32비트
    • 메모리 조각이 비어있는지 알려주는 설정값(flag) - 1비트
  • 할당 가능한 메모리 조각을 payload라고 함 (메모리 주소)

3.4.5 메모리 할당 상태 추적하기

한조각은 4바이트

  • 16/1: 할당된 메모리 조각 크기가 16바이트를 의미
  • 32/0 : 여유 메모리 조각이 32 바이트
  • 0/1: 끝을 표시하는 특수한 표시로 4바이트

이 방식으로 메모리 조각의 여유/할당 상태 파악 및 추적할 수 있음

3.4.6 어떻게 여유 메모리 조각을 선택할 것인가: 할당 전략

  • 4바이트 메모리를 요청받을 때 요구사항을 충족하는 여유 메모리가 두조각이 있음
    • 8/0, 32/0 중 어떤것을 반환할 것인가? 다양한 할당 전략 방식이 있음

메모리 할당 전략 방식

1. 최초 적합 방식

  • 제일 앞부터 탐색하다가 가장 먼저 발견된 요구사항을 만족하는 항목을 반환
  • 단순하지만, 처음부터 사용가능한 메모리 조각을 찾으므로 앞부분에 작은 메모리 조각이 많이 남을 가능성이 높음

2. 다음 적합 방식

  • 최초 적합 방식과 유사하지만 메모리를 요청할 때 처음부터 검색하는 대신 적합한 여유 메모리 조각이 마지막으로 발견된 위치에서 시작한다는 점이 다름
  • 탐색 시작 위치가 달라져, 더 빠르게 여유 메모리 조각을 탐색할 수 있음
  • 단점: 메모리 사용률은 최초 적합 방식에 미치지 못한다는 것이 연구로 밝혀짐

3. 최적 적합 방식

  • 사용 가능한 메모리 조각을 모두 찾은 후 요구 사항을 모두 만족하면서 크기가 가장 작은 조각 반환
  • 메모리를 더 잘 활용한다는 장점이 있음
  • 사용가능한 모든 메모리 조각을 탐색하기 때문에 빠르지 않음

실제로는 더 복잡한 원리로 적합한 방식을 찾아 할당

3.4.7 메모리 할당하기

  • 12바이트 메모리를 요청했을 때 적절한 여유 메모리 조각이 12 바이트라고 가정
    • 헤더인 4바이트를 제외한 나머지 크기

  • 할당된 것으로 표시하고 머리 정보 뒤에 따라오는 메모리 조각의 주소를 요청자에게 반환하면 됨
  • 위는 이상적인 경우로 12바이트 메모리를 요청했을 때 찾아낸 여유 메모리 조각의 크기가 더 큰 경우가 대부분
  • 아래와 같이 찾아낸 메모리 조각이 32바이트라면? 메모리가 낭비되고 내부 단편화(fragmentation) 발생함

내부 단편화의 예

  • 이 문제를 해결하기 위해 여유 메모리 조각을 두개로 분할하여 앞부분은 할당한 후 반환하고 뒷부분은 좀 더 작은 크기의 새로운 여유 메모리 조각으로 만듦

3.4.8 메모리 해제하기

  • 사용자가 메모리를 요청할 때 얻은 주소를 ADDR이라고 가정
  • free(ADDR)을 호출하면 매개변수인 ADDR에서 머리 정보 크기인 4바이트를 빼는 것으로 메모리 조각의 머리 정보 얻을 수 있음
  • 머리 정보에서 얻은 할당 설정값을 여유 메모리로 바꾸면 해제가 완료됨

메모리 해제 시 중요한 점 하나

  • 해제되는 메모리 조각과 인접한 메모리 조각이 여유 메모리 조각일 때 단순히 해제 여부만 기록하면 아래 상황 발생

  • 해제된 메모리 조각에 인접한 아래쪽 메모리 조각도 비어있음
  • 메모리를 해제 할 때 둘을 합치는게 나을까? 그대로 두는게 나을까?

그대로 두는 경우

  • 20 바이트 요청이 오는 경우 두 조각 중 어느 것도 요구사항을 만족시키지 못함

메모리를 해제 할 때 메모리 조각을 병합할 때

  1. 즉시: 비교적 간단하지만 부담이 발생. 하지만 간단해서 여전히 이 전략을 많이 선택
  2. 요구사항을 충족하는 여유 블록을 찾을 수 없을 때: 실제 메모리 할당자가 선택하는 전략

3.4.9 여유 메모리 조각을 효율적으로 병합하기

  • 해제하는 메모리 조각의 위 아래가 모두 비어있다면? 아래는 헤더 정보로 알 수 있지만 위의 정보는 어떻게 알 수 있나?

  • 메모리 조각 끝에 footer 정보를 추가

  • 조각의 꼬리 정보는 그 다음에 위치한 조각의 머리 정보와 인접해 있어 현재 조각의 머리 정보에서 4바이트를 빼면 이전 조각의 꼬리 정보를 획득할 수 있음

  • header와 footer 정보는 메모리 조각을 doubly linked list로 만듦
반응형
반응형

이 글은  컴퓨터 밑바닥의 비밀 chapter 3.2-3.3 의 내용을 읽고 요약한 글입니다. 

3.2 프로세스는 메모리 안에서 어떤 모습을 하고 있을까?

3.2.1 가상 메모리: 눈에 보이는 것이 항상 실제와 같지는 않다

  • 모든 프로세스의 코드 영역은 0x400000에서 시작
    • 서로 다른 두개의 프로세스가 메모리를 할당하기 위해 malloc을 호출하면 동일한 시작 주소를 반환할 가능성이 매우 높음

Ubuntu 에서 테스트

// malloc_test.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    void *ptr = malloc(10);  // Allocate 10 bytes
    printf("Address returned by malloc: %p\\n", ptr);
    free(ptr);  // Don't forget to free the memory
    return 0;
}

$ ./malloc_test Address returned by malloc: 0x56342fa8d260
$ ./malloc_test Address returned by malloc: 0x55a3e5a9d010

다른 주소가 반환됨. 이유는? → ASLR 이라는 기술이 최근 OS에는 적용되어있음

ASLR (Address Space Layout Randomization)

  • 스택, 힙, 동적 라이브러리 영역의 주소를 랜덤으로 배치해서 공격에 필요한 target address를 예측하기 어렵게 만드는 기술

ASLR 기술을 끄고 테스트하면 같은 주소가 반환되는 걸 볼 수 있다

$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
$ ./malloc_test
$ Address returned by malloc: 0x40068c
$ ./malloc_test
$ Address returned by malloc: 0x40068c
  • 두 프로세스가 모두 같은 주소에 데이터를 쓸 수 있다는 의미인데 괜찮은가?

⇒ 주소값은 가짜 주소(가상 메모리 주소)이고 메모리에 조작이 일어나기 전 실제 물리 메모리 주소로 변경되기 때문에 문제 되지 않음

실제 물리 메모리 구조 예시

주목할 2가지 사항

  1. 프로세스는 동일한 크기의 chunk로 나뉘어 물리 메모리에 저장
    - 위 그림에서 힙 영역은 3개의 chunk로 나뉨
  2. 모든 조각은 물리 메모리 전체에 무작위로 흩어져 있음

보기에 아름답지 않지만 운영 체제가 프로세스에 균일한 가상의 주소 공간을 제공하는 것을 방해하지는 않음 → 가상 메모리와 물리 메모리 사이의 mapping을 나타내는 page table로 관리

3.2.2 페이지와 페이지 테이블: 가상에서 현실로

  • 각각의 프로세스에는 단 하나의 페이지 테이블만 있어야 함
  • mapping은 ‘page’ 라는 단위로 이루어짐
    • 프로세스의 주소 공간을 동일한 크기의 ‘조각’으로 나누고, 이 ‘조각’을 페이지(page)라고 부름
  • 그러므로 두 프로세스가 동일한 메모리 주소에 기록하더라도 페이지 테이블 통해 실제는 다른 물리 메모리 주소에 저장됨

 

3.3 스택 영역: 함수 호출은 어떻게 구현될까?

아래 코드의 문제점은?

void func(int a)
{
	if(a>100000000)
	{
		return;
	}
	
	int arr[100] = { 0 };
	
	func(a + 1);
}
  • 함수 실행 시간 스택(runtime stack)과 함수 호출 스택(call stack) 이해 필요

3.3.2 함수 호출 활동 추적하기: 스택

  • A, B, C, D 4가지 단계가 존재하고 아래그림 처럼 의존성을 가짐

단계별로 진행 과정

  • A→B→D→B→A→C→A
  • 선입 선출(Last In First Out, LIFO) 순서로 stack 과 같은 데이터 구초가 처리하기 적합

 

3.3.3 스택 프레임 및 스택 영역: 거시적 관점

  • 함수 실행시의 자신만의 ‘작은 상자’가 필요한데 이를 call stack 혹은 stack frame 이라고 함
  • 스택은 낮은 주소 방향으로 커지므로 아래와 같이 표현됨

  • stack frame에는 어떤 정보들이 포함되는지?

3.3.4 함수 점프와 반환은 어떻게 구현될까?

  • 함수 A가 함수 B를 호출하면, 제어권이 A에서 B로 옮겨짐
    • 제어권: CPU가 어떤 함수에 속하는 기계 명령어를 실행하는지 의미

제어권이 넘어갈 때는 2가지 정보가 필요함

  1. 반환(return): 어디에서 왔는지에 대한 정보
    • 함수 A의 명령어가 어디까지 실행되었는지에 대한 정보
  2. 점프(jump): 어디로 가는지에 대한 정보
    • 함수 B의 첫 번째 기계 명령어가 위치한 주소

위의 정보는 어디서 가져오는지? → 스택 프레임!

함수 A가 함수 B를 호출할 때 CPU는 함수 A의 기계 명령어(주소: 0x400564)를 실행중이라 가정

  • CPU는 다음 기계 명령어를 실행하는데 call 뒤에 명령어 주소가 함수 B의 첫번째 기계 명령어
    • 이 명령어를 실행한 직후 CPU는 함수 B로 점프하게 됨
  • 함수 B실행이 완료되면 어떻게 함수 A로 돌아오나?
    • call 명령어 실행 후 지정한 함수로 점프 + call 명령어 다음 위치 주소(0x40056a)를 함수 A의 스택 프레임에 넣음

call 명령어를 실행하면 반환주소가 스택 프레임에 저장됨

반환 주소가 추가되면서 스택 프레임이 아래 방향으로 조금 커짐

  • 함수 B에 대응하는 기계 명령어를 실행하면서 B에 대한 스택 프레임도 추가됨
  • 함수 B의 마지막 기계 명령어인 ret은 CPU에 함수 A의 스택 프레임에 저장된 반환주소로 점프하도록 전달하는 역할

 

3.3.5 매개변수 전달과 반환값은 어떻게 구현될까?

대부분의 경우 레지스터를 통해 매개변수와 반환값을 전달

  • 함수 A가 B를 호출하면, A는 매개변수를 상응하는 레지스터에 저장
  • CPU가 함수 B를 실행할 때 이 레지스터에서 매개변수 정보를 얻을 수 있음
  • CPU 내부의 레지스터 수가 제한되는 경우 나머지는 스택 프레임에 넣음

스택 프레임에 함수 호출에 필요한 매개변수 보관

3.3.6 지역 변수는 어디에 있을까?

  • 레지스터에 저장할 수 있지만 로컬 변수가 레지스터 수보다 많으면 스택프레임에 저장

 

3.3.7 레지스터의 저장과 복원

  • 함수 A와 B가 지역변수 저장을 위해 모두 레지스터를 사용하면 값이 덮어써 질 수 있음
  • 그렇기 때문에 초기에 저장된 값을 레지스터에서 사용하고 나면 다시 그 초기값을 함수의 스택 프레임에 저장해야 함

 

3.3.8 큰 그림을 그려보자, 우리는 지금 어디에 있을까?

void func(int a)
{
	if(a>100000000)
	{
		return;
	}
	
	int arr[100] = { 0 };
	
	func(a + 1);
}
  • 앞에서 본 코드를 다시 보면, 자기 자신 함수를 100000000번 호출
  • 호출 할 때마다 스택 프레임이 함수 실행시 정보를 저장하기 위해 생성되며, 함수 호출 단계가 증가하며 스택 영역이 점점 더 많은 메모리 차지 → stack overflow 발생

위 과정 시각화 링크

 

Python Tutor code visualizer: Visualize code in Python, JavaScript, C, C++, and Java

Please wait ... your code is running (up to 10 seconds) Write code in Python 3.11 [newest version, latest features not tested yet] Python 3.6 [reliable stable version, select 3.11 for newest] Java C (C17 + GNU extensions) C++ (C++20 + GNU extensions) JavaS

pythontutor.com

  • 코드가 실행되면서 stack frame이 계속 쌓이는 모습을 볼 수 있음 

 

반응형
반응형

이 글은 책 컴퓨터 밑바닥의 비밀 chapter 3.1 의 내용을 읽고 요약한 글입니다. 

3.1 메모리의 본질, 포인터와 참조

3.1.1 메모리의 본질은 무엇인가? 사물함, 비트, 바이트, 객체

  • 메모리는 메모리 셀(memory cell)로 구성되며 셀에는 0과 1 (1bit) 가 보관될 수 있음
  • 1bit로는 표현할 수 있는 정보가 너무 적기 때문에 8개를 묶어 byte로 표현
  • byte는 메모리 내 자신의 주소를 가지며 memory address 라고 함
  • 1byte도 $2^{8}$=256 개의 조합만 만들 수 있으므로 더 많은 정보를 포함하기에는 부족
  • 12바이트를 묶어서 사용하며 프로그래밍 언어에서는 구조체(structure)또는 객체(object)라고 표현

 

3.1.2 메모리에서 변수로: 변수의 의미

  • java script/python 등의 고급 프로그래밍 언어는 사용할 수 없고 8byte만 사용가능한 메모리가 주어진다면? 메모리 읽기와 쓰기를 직접 수행해야 함
 

  • 8칸의 메모리 공간이 있고 옆에 붙은 번호가 각각 메모리의 주소

1 + 2 값을 계산하고 싶다고 가정하면,

  • 숫자 1과 2를 메모리에 저장해야 함 (메모리 값을 읽어 레지스터에 저장해야 CPU가 연산 수행 가능)
  • 숫자 1을 메모리 주소 6에 넣기 위해 store라는 명령어를 사용한다면,
store 1 6
  • 숫자 2개중 하나는 저장할 숫자 값이고 하나는 메모리 주소

쓰기를 위해 load 라는 명령어를 사용한다면,

load r1 6
  • 명령어 뜻 모호
    • 숫자 6을 r1 레지스터에서 읽는거지,
    • 메모리 주소 6에 저장된 숫자를 r1레지스터에 읽는건지,

즉, 메모리 주소와 숫자 값을 구분하기 위한 방법 필요

  • 예를 들어 $ 기호가 붙어 있으면 값이고, $ 기호가 없다면 메모리 주소를 의미
store $1 6
load r1 6

메모리 주소 6에 1의 값을 저장

  • 이제 주소 6은 숫자 1을 나타냄 (주소 6 → 숫자 1)
  • 하지만 ‘주소 6’이라는 표현은 익숙하지 않기 때문에 쉬운 별칭 필요 (a 같은) ⇒ 변수
a = 1

a 변수라는 의미

  • 값 1을 나타냄
  • 값은 메모리 주소 6에 저장됨
b = a

위 표현은? b변수를 위해 메모리 주소를 하나 할당할 수 있음

하지만 아래그림처럼 a 변수가 여러 바이트(5bytes)를 차지하는 데이터를 나타내고 b=a 를 표현해야 한다면, 메모리 공간이 부족한데 방법은?

3.1.3 변수에서 포인터로: 포인터 이해하기

  • b 변수가 a변수를 가리키고 있다면 데이터의 복사본을 만들 필요가 없음

  • a 변수는 메모리 주소 3에 위치하므로 b 변수에 메모리 주소 숫자 3을 저장 → 포인터

포인터를 메모리 주소로만 이해한다면 간접 주소 지정을 알아야 함 (indirect addressing)

load r1 1 
  • 메모리 주소 1에 있는 값(숫자 3)을 r1 레지스터에 적재하는데, 메모리 주소 1에는 주소값이 있기 때문에 이를 나타내 줘야 함
load r1 @1
  • 메모리 주소1 → 메모리 주소 3→ 데이터 값(1)

어셈블리어에는 변수라는 개념이 없기 때문에 위와 같이 간접주소 지정 계층을 알아야 하지만 고급 언어에서는 변수를 사용하면 됨

메모리 주소 1 -> 메모리 주소 3 -> 데이터 # 어셈블리어 수준
b -> 데이터 # 고급언어 수준

3.1.4 포인터의 힘과 파괴력: 능력과 책임

#include <stdio.h>

void main()
{
	int a = 1;
	printf("variable a is in %p\\n", &a);
}

variable a is in 0x7fff328

  • 포인터를 통해 메모리를 직접 조작할 수 있는 능력은 강력하지만, 모든 상황에 필요한 것은 아니며, 포인터 없는 프로그래밍 언어에도 대신 사용할 수 있고 포인터를 한번 더 추상화한 참조가 있음

3.1.5 포인터에서 참조로: 메모리 주소 감추기

  • 포인터는 메모리를 추상화하 것이고 참조는 포인터를 한번 더 추상화 한 것
반응형
반응형

본 글은 책 "혼자 공부하는 컴퓨터 구조+운영체제" 의 Chapter 6를 읽고 정리한 내용입니다.

06-1 RAM의 특징과 종류

RAM의 특징

  • 실행할 프로그램의 명령어와 데이터가 저장되는 곳
  • 전원을 끄면 저장된 명령어와 데이터가 모두 날아감 → 휘발성 저장 장치(volatile memory)
  • 비휘발성 저장장치(non-volatile memory): 전원이 꺼져도 저장된 내용이 유지되는 저장 장치로하드디스크, SSD, USB 메모리 등과 같은 보조기억장치가 있음
  • 보조기억장치는 전원을 꺼도 내용을 유지하지만 CPU가 직접 접근하지 못함

⇒ 보조기억장치에는 보관할 대상을 저장하고 RAM에는 실행할 대상을 저장

 

RAM의 용량과 성능

  • CPU가 실행하고 싶은 프로그램이 보조기억장치에 있다면 이를 RAM으로 가져와야 함
  • RAM의 용량이 적다면 보조기억장치에서 RAM으로 실행할 프로그램을 가져오는 일이 잦아 실행 시간이 길어짐

RAM의 용량이 적은 경우
RAM용량이 프로그램 A,B,C를 모두 저장할 정도로 충분히 큰 경우

 

RAM의 종류

DRAM

  • Dynamic RAM
  • 저장된 데이터가 동적으로 변하는(사라지는) RAM을 의미
    • 시간이 지나면 저장된 데이터가 점차 사라지는 RAM으로 데이터의 소멸을 막기 위해 일정 주기로 데이터를 재활성화(다시 저장) 해야 함
  • 위 단점에도 불구하고 아래 장점들 때문에 가장 많이 쓰임
    • 소비 전력이 비교적 낮음
    • 저렴
    • 집적도가 높아 대용량 설계 용이 (더 작고 빽빽하게 만들 수 있다는 의미)

SRAM

  • Static RAM
  • 저장된 데이터가 변하지 않는 RAM으로 일반적으로 DRAM보다 빠름
  • 대용량으로 만들어질 필요는 없지만 속도가 빨라야하는 곳에 쓰임 (ex) 캐시 메모리)

 

SDRAM

  • Synchronous Dynamic RAM
  • 클럭 신호와 동기화된 발전된 형태의 DRAM
    • 클럭에 맞춰 동작하며 클럭마다 CPU와 정보를 주고받을 수 있는 DRAM

DDR SDRAM

  • Double Data Rate SDRAM 으로 최근 가장 흔히 사용됨
  • 대역폭을 넓혀 속도를 빠르게 만든 SDRAM

* 대역폭(Data rate): 데이터를 주고받는 길의 너비

SDRAM을 SDR(Single Data Rate) SDRAM라고도 부름

  • DDR2 SDRAM은 DDR SDRAM보다 대역폭이 두 배 넓은 SDRAM (SDR SDRAM 보다 4배 넓음)
  • DDR3 SDRAM : DDR2 SDRAM보다 대역폭이 2배 넓음 (SDR SDRAM보다 8배)
  • DDR4 SDRAM : DDR3 SDRAM보다 대역폭이 2배 넓음 (SDR SDRAM보다 16배)

 

06-2 메모리의 주소 공간

메모리에 저장된 정보의 위치를 나타내는 주소는 두 종류가 있음

  • 물리주소: 메모리 하드웨어가 사용하는 주소
  • 논리주소: CPU와 실행중인 프로그램이 사용하는 주소

물리주소와 논리주소

  • CPU가 이해하는 주소가 논리 주소라고는 해도 CPU가 메모리와 상호작용하려면 논리주소와 물리주소 간의 변환의 이루어져야 함
    • 아래 그림에서 인터넷 브라우저의 0번지와 게임의 0번지는 CPU가 이해하기는 다르지만 실제 물리주소로 변환되지 않으면 메모리가 이해할 수 없음

⇒ CPU와 주소 버스 사이에 위치한 메모리 관리 장치(MMU, Memory Management Unit)라는 하드웨어에 의해 논리주소 ↔ 물리주소 변환이 수행됨

MMU는 CPU가 발생시킨 논리 주소에 베이스 레지스터(프로그램의 기준 주소) 값을 더하여 논리주소→물리주소로 변환

  • 베이스 레지스터: 프로그램의 가장 작은 물리 주소로 프로그램의 첫 물리 주소를 저장하는 셈

  • CPU가 "프로그램 A의 100번지 데이터"를 삭제하라고 명령하면, MMU를 통해 베이스 레지스터 값을 찾고 논리주소 값을 더해 실제 물리 주소 값을 얻은 다음 메모리에 접근하여 데이터 삭제

  • CPU가 "프로그램 C의 100번지 데이터"를 삭제하라고 명령하면, MMU를 통해 해당 프로그램의 베이스 레지스터 값을 찾고 논리 주소 값을 더해 실제 물리주소 값을 얻은 다음, 메모리에 접근하여 데이터 삭제

 

메모리 보호 기법

  • 아래 CPU의 명령어는 안전할까?

메모장 1500번지에 숫자 100을 저장하라고 CPU가 명령했지만 메모장은 논리주소 범위가 0~999로 범위를 벗어남

  • 안전하지 않고 실행되어서는 안됨
  • 프로그램의 논리 주소 영역을 벗어났기 때문
  • 위 명령어가 실행된다면 메모장 프로그램은 애꿏은 인터넷 브라우저 프로그램에 숫자 100을 저장

 

  • 인터넷 브라우저 프로그램의 명령어가 자신과 전혀 관련없는 게임 프로그램 정보를 삭제하게 됨
  • 다른 프로그램의 영역을 침범할 수 있는 명령어는 위험하기 때문에 논리 주소 범위를 벗어나는 명령어 실행을 방지하고 실행중인 프로그램이 다른 프로그램에 영향을 받지 않도록 보호할 방법이 필요

한계 레지스터 (limit register)

  • 베이스 레지스터가 실행중인 프로그램의 가장 작은 물리 주소를 저장한다면, 한계 레지스터는 논리 주소의 최대 크기를 저장
    • 베이스 레지스터 값 ≤ 프로그램의 물리 주소 범위 < 베이스 레지스터 값 + 한계 레지스터 값

CPU가 접근하려는 논리 주소는 한계 레지스터가 저장한 값보다 커서는 안됨

  • 프로그램 A의 크기, 즉 한계 레지스터가 150인 상황
  • CPU가 200번지를 삭제하라는 명령어를 보내면 논리 주소가 한계 레지스터 값보다 커 실행될 수 없음

⇒ CPU는 메모리에 접근하기 전에 접근하고자 하는 논리 주소가 한계 레지스터보다 작은지를 항상 검사

CPU가 한계 레지스터보다 높은 논리 주소에 접근하려고 하면 인터럽트(트랩)을 발생시켜 실행을 중단시킴

 

참고

 


1. 책 "혼자 공부하는 컴퓨터 구조+운영체제"
2. 유튜브 "혼자 공부하는 컴퓨터 구조 + 운영체제"

 
반응형

'OS' 카테고리의 다른 글

운영체제를 공부해야하는 이유와 커널  (0) 2024.07.14
캐시메모리  (0) 2024.07.07
CPU 성능 향상 기법  (0) 2024.07.02
명령어  (0) 2024.06.30
데이터  (0) 2024.06.27

+ Recent posts