jun-wiki

View My GitHub Profile

Posts (Latest 10 updated) :
Read all
Contents:
  1. 9.6 주소의 번역
    1. 9.6.1 캐시와 VM의 통합
    2. 9.6.2 TLB를 활용한 주소 번역 속도의 개선
    3. 9.6.3 다중 레벨 페이지 테이블
    4. 9.6.4 종합 구현: 종단 주소 번역
      1. 요점
      2. 흐름
      3. 예시 경로
      4. 비트 분할(이 시스템 전제)
  2. 9.7 사례 연구: 인텔 코어 i7/ 리눅스 메모리 시스템
    1. 핵심 흐름
    2. 9.7.1 코어 i7에서의 주소 번역
      1. (1) 가상 주소 생성 & TLB 조회
      2. (2) 다단계 페이지 테이블 탐색
      3. (3) 캐시 계층 조회(물리주소 기반)
      4. (4) 메인 메모리(DRAM) 접근
    3. 9.7.2 리눅스 가상 메모리 시스템
      1. (1) 주소 공간과 전환
      2. (2) 사용자 공간 vs 커널 공간
      3. (3) 페이지 폴트 & 교체
      4. (4) 정리
  3. 9.8 메모리 매핑
    1. 9.8.1 다시 보는 공유 객체
    2. 9.8.2 다시 보는 fork 함수
    3. 9.8.3 다시 보는 execve 함수
    4. 9.8.4 함수를 이용한 사용자수준 메모리 매핑

9.6 주소의 번역

가상 주소를 물리 주소로 변환하는 거에 대해 나온다

MMU = CPU가 만든 가상주소를 물리 주소로 변환하는 하드웨어 구성요소

CPU의 제어 레지스터 PTBR(페이지 테이블 기준 레지스터)는 현재 페이지 테이블을 가리킴

가상 주소(VA)가상 페이지 오프셋(VPO)가상 페이지 번호(VPN) 로 구성됨

MMU는 VPN으로 적절한 페이지 테이블 엔트리(PTE) 선택

  • 페이지 히트시 :

    • MMU는 페이지 테이블에서 PTE를 찾아 물리 주소 구성 후, 메인 메모리에서 데이터 가져옴
  • 페이지 폴트(오류)시:

    • 커널의 페이지 폴트 핸들러가 디스크에서 해당 페이지를 메모리로 로드 후, 오류 명령어 재실행



9.6.1 캐시와 VM의 통합

SRAM 캐시에 접근하기 위해 가상 vs 물리 메모리 쓸지 정하는데 보통 물리 메모리 쓴다고 한다

그리하여야 여러 프로세스가 동시에 캐시 블록을 가질 수 있고,

동일한 가상 페이지 블록 공유하기 용인하며,

주소 변환 과정에서 접근 권한이 확인되어 보호 문제도 따로 처리할 필요가 없다



9.6.2 TLB를 활용한 주소 번역 속도의 개선

MMU 내에는 TLB(Translation Lookaside Buffer) 라는, MMU가 PTE를 참조할 때 비용을 줄이기 위한 캐시가 포함되어 있다

TLB는 가상 주소 지정 방식의 캐시로 각 라인은 단일 PTE로 구성된 블록을 담고 있다

TLB 인덱스(TLBI) 및 TLB 태그(TLBT) 필드는 가상 주소의 가상 페이지 번호(VPN) 에서 추출된다

  • TLB 적중(hit)시의 과정 :

    1. CPU가 가상 주소 생성

    2. MMU가 TLB에 접근

    3. TLB가 히트시 TLB는 물리 페이지 번호(PPN)를 반환

    4. MMU는 PPN을 사용하여 물리 주소 형성 후 이를 캐시/메인 메모리에 보냄

    5. 캐시/메인 메모리는 요청된 데이터를 CPU로 반환



9.6.3 다중 레벨 페이지 테이블

단일 페이지 테이블을 사용하면 과도하게 메모리가 상주해야 한다

이를 해결 하기 위해 다중 레벨 페이지 테이블이 사용된다


다중 레벨 페이지 테이블에서 가상 주소k개의 VPN(가상 페이지 번호)과 하나의 VPO(가상 페이지 오프셋)로 분할

각 VPN은 해당 레벨의 페이지 테이블에서 인덱스로 사용

레벨 j 테이블의 PTE는 레벨 j+1 페이지 테이블의 시작 주소를 가리킴

최하위 레벨 테이블의 PTEPPN(물리 페이지 번호) 또는 디스크 블록 주소를 포함한다



9.6.4 종합 구현: 종단 주소 번역

요점

  • VA는 **VPN VPO**로, PA는 **PPN PPO로 분해된다
    **VPO=PPO
  • TLB(가상 주소 지정 방식의 캐시) → 페이지테이블 →(필요시) 폴트 처리 → PA 조립 → L1 캐시의 순서로 흐른다

  • TLB가 페이지테이블 접근 지연을 숨기고, L1 캐시는 DRAM 지연을 숨긴다



흐름

  1. CPU가 VA 생성 VA의 하위 p비트는 VPO(여기선 64B 페이지 → p=6), 상위 비트는 VPN.

  2. TLB 조회(가상 인덱스)

    • VPN의 일부가 TLB 세트 인덱스(TLBI), 나머지가 태그(TLBT)

    • 히트면 저장돼 있던 PPN 획득

    • 미스면 ③으로

  3. 페이지 테이블 조회(물리 메모리)

    • VPN으로 PTE를 찾아 읽고 valid/권한 점검

    • 유효하면 PPN 얻고 TLB 채움

    • 무효/권한 위반이면 페이지 폴트 → 커널이 필요한 페이지를 디스크→DRAM으로 페이지 인(또는 예외 처리) 후 재시작

  4. 물리 주소 조립

    • **PA = PPN   VPO**
  5. L1 D-캐시 접근(물리 주소 기반)

    • PA에서 CO(블록 오프셋), CI(세트 인덱스), CT(태그) 추출

    • 히트면 데이터 반환

    • 미스면 하위 계층(메모리/하위 캐시)에서 블록을 가져와 채운 뒤 반환



예시 경로

  • VA 0x03d4TLB 히트로 PPN=0x0d → PA 0x0354 조립 → 캐시 세트 0x5 태그 0x0d 히트 → 바이트 반환

  • 다른 경로: TLB 미스→ PTE 읽기(또는 페이지 폴트) → TLB 채움 → 캐시 접근(히트/미스)



비트 분할(이 시스템 전제)

  • VA 14비트, PA 12비트, 페이지 64B

    • VPO/ PPO = 6비트, VPN = 8비트, PPN = 6비트
  • TLB: 4세트 → VPN의 하위 2비트=TLBI, 상위 6비트=TLBT

  • 캐시: 4B 라인, 16세트 → CO=2비트, CI=4비트, CT=6비트



요약: VA →(TLB/페이지테이블)→ PPN 결定 → PA 조립 →(캐시)→ 데이터라는 두 단계 번역/캐싱 파이프라인이, 각각 DRAM·디스크 지연을 숨겨 전체 접근을 빠르게 한다





9.7 사례 연구: 인텔 코어 i7/ 리눅스 메모리 시스템

코어 i7 시스템의 주요 구성 요소

  • 프로세서 패키지: 4개의 코어, 모든 코어가 공유하는 대규모 L3 캐시, DDR3 메모리 컨트롤러

  • 각 코어: TLB 계층, 데이터 및 명령어 캐시 계층, 다른 코어 및 외부 I/O 브리지와 직접 통신하는 QuickPath 링크를 포함

  • 캐시 특성:

    • TLB: 가상 주소 지정 방식, 4-way 집합 연관

    • L1, L2, L3 캐시: 물리 주소 지정 방식, 64바이트 블록 크기. L1, L2는 8-way 집합 연관, L3는 16-way 집합 연관

  • 페이지 크기: 시작 시 4KB 또는 4MB로 구성 가능하며, 리눅스는 4KB 페이지를 사용


핵심 흐름

핵심:
Core i7 하드웨어(TLB·다단계 페이지 테이블·계층적 캐시)와 리눅스 커널이 협업해
가상 주소→물리 주소 변환을 빠르게 수행한다
전체 흐름은

  • 가상 주소 생성

  • → TLB 조회

  • → 페이지 테이블 탐색

  • → 캐시 조회

  • → DRAM 접근



9.7.1 코어 i7에서의 주소 번역

(1) 가상 주소 생성 & TLB 조회

  • VA 분해: VA = VPN(상위 비트) + VPO(하위 오프셋)

  • TLB: 먼저 TLB에서 VPN→PPN 매핑을 찾는다(히트 시 즉시 변환 완료)
    L1 D-TLB 64엔트리, L1 I-TLB 128엔트리, L2 통합 TLB 512엔트리 규모


(2) 다단계 페이지 테이블 탐색

  • TLB 미스 시 하드웨어가 x86-64의 4단계 페이지 테이블을 따라간다

  • 과정: CR3에서 최상위 테이블 물리주소 획득
    → VPN을 4개 인덱스로 나눠 레벨1
    →4 테이블을 순차 인덱싱
    → 최종 PTE에서 PPN 획득
    중간에 유효 비트/권한 비트도 검사

  • 완료: PPN을 얻으면 TLB 갱신 후, VPO와 결합최종 물리주소(PA) 형성


(3) 캐시 계층 조회(물리주소 기반)

  • 특징: 캐시는 물리 주소로 인덱싱/태그 비교(프로세스 간 일관성 용이)
    먼저 L1에서 인덱스/태그 확인
    히트 시 즉시 반환

  • 미스 처리: L1 미스→L2 조회→L3(공유 LLC) 조회
    각 단계 히트 시 상위 레벨로 채워 넣음


(4) 메인 메모리(DRAM) 접근

  • 전 캐시 미스 시 통합 메모리 컨트롤러가 DRAM에서 라인(예: 64B)을 읽어와 L3L2L1에 채우고 CPU에 전달
    멀티소켓이면 QPI로 원격 메모리에 접근 가능

  • 요지: TLB와 캐시가 각각 페이지 탐색 지연·DRAM 지연을 줄여 전체 접근을 가속



9.7.2 리눅스 가상 메모리 시스템

(1) 주소 공간과 전환

  • 격리: 프로세스마다 독립 VA 공간. 컨텍스트 스위치 때 CR3 교체로 매핑 전환

  • TLB 동기화: 전환 시 보통 TLB 플러시(PCID 등 예외도 있음)


(2) 사용자 공간 vs 커널 공간

  • 사용자 공간: 코드/데이터(.bss), , mmap/공유 라이브러리, 스택으로 구성

  • 커널 공간: 모든 프로세스에 공통 매핑, 사용자 모드 접근 불가
    커널 코드/데이터, 물리 메모리 직접 매핑(direct mapping), 프로세스별 커널 자료구조(커널 스택·task struct·페이지 테이블 등)


(3) 페이지 폴트 & 교체

  • 수요 페이징: 유효 비트=0 접근 시 페이지 폴트
    → 커널이 올바른 접근이면 디스크에서 읽거나 새 페이지 할당
    PTE 업데이트 후 재시도
    잘못된 접근이면 종료


(4) 정리

  • 리눅스는 하드웨어의 페이지 테이블/​TLB를 활용해 보호·격리·교체를 담당, 하드웨어는 고속 변환과 접근을 수행하여 큰 연속 가상 메모리 착시와 효율적 물리 메모리 사용을 동시에 달성





9.8 메모리 매핑

가상 메모리의 초기 내용을 디스크의 객체와 연결해 초기화하는 것을 리눅스에서 메모리 매핑이라 명칭

  • 객체 유형:

    1. 리눅스 파일 시스템의 일반 파일:

      • 실행 가능 객체 파일 같은 일반 디스크 파일의 연속 세션에 매핑 가능

      • 파일 섹션은 페이지 크기 조각으로 나뉨

      • 각 조각은 가상 페이지의 초기 내용을포함

      • CPU가 처음 접근전까지는 실제 물리 메모리 X

    2. 익명,무기명 파일:

      • 파일 시스템에 해당하지 않는 익명 객체에 매핑 가능

      • 적당한 희생 페이지 찾아 0으로 초기화

      • 실제로 데이터가 디스크와 메모리 사이에서 이동하지 않음 (무요구 $demand-zero$ 페이지)


어찌되었든 가상페이지가 초기화 된 후에는 커널이 관리하는 특별한 스왑 파일 사이에서 스왑 인, 아웃한다

중요한 점은 스왑 공간이 프로레스들에 할당된 전체 가상페이지의 양을 제한한다는 것이다



9.8.1 다시 보는 공유 객체

  • 파일 공유의 효율성:

    • 여러 프로세스가 동일한 영역을 사용하는 경우, 각 프로세스마다 별도로 복사본 만들어주는건 비효율적이다


  • 공유 shared 객체, 사적 private 객체

    • 공유 객체

      • 프로세스가 공유 객체를 가상 메모리 영역에 매핑 시,
        해당 영역에 대한 모든 쓰기는 공유 객체를 매핑한 다른 프로세스에게도 보이며,
        원본 디스크 객체에도 변경 사항이 반영
    • 사적 객체

      • 사적 객체에 매핑된 영역에 대한 변경 사항은 다른 프로세스에게 보이지 않으며,
        원본 디스크 객체에도 반영되지 않음


공유 객체는 여러 공유 영역에 매핑되어도 물리 메모리에는 단일 복사본만 저장하면 됨


  • Copy-on-Write:

    • 사적 객체는 copy-on-write 기법을 통해 가상 메모리에 매핑

    • 물리메모리에 단일 복사본만 존재하다가 사적 영역의 페이지에 쓰려 시도할 시에
      해당 페이지의 사본 생성 후, 프로세스의 페이지 테이블 엔트리가 새 사본을 가르키도록 업데이트



9.8.2 다시 보는 fork 함수

fork 함수 호출 시, 커널은 새 프로세스에 대한 데이터 구조 생성 후 PID1 할당

새 프로세스의 가상 메모리 생성을 위해 현제 프로세스의 mm_struct, area struct, 페이지 테이블의 정확한 복사본을 생성

이후, 두 프로세스의 모든 페이지들을 읽기-허용으로 표시하고, 두 프로세스의 영역 구조체들을 사적 copy-on-wite로 표시

그 결과, 프로세스가 쓰기 작업 수행 시 copy-on-write 메커니즘으로 새 페이지 생성해 각 프로세스에 대해 사적 주소공간 추상화 유지 가능



9.8.3 다시 보는 execve 함수

execve 함수는 현재 프로세스 내에 새 프로그램 로드 후 실행하여 현재 프로그램 교체

이 과정에서 가상 메모리 및 메모리 매핑 사용


  1. 기존 사용자 영역 제거

    • 현재 프로세스의 가상 주소 공간에 있는 기존 사용자 영역(area struct들)을 삭제
  2. 새 사적 영역 매핑

    • 새 프로그램의 코드, 데이터, bss, 스택 영역에 대한 새 area struct를 생성

    • 이 새 영역들은 모두 private(사적) copy-on-write 방식

  3. 공유 영역들을 매핑

    • 프로그램이 표준 C 라이브러리 같은 공유 객체와 연결되어 있을 시, 동적 링크 후에 사용자의 가상 주소공간의 공유 영역으로 매핑
  4. 프로그램 카운터(PC)를 설정

    • 마지막으로 execve는 현재 프로세스 컨텍스트의 프로그램 카운터를 코드 영역의 시작 지점으로 설정



9.8.4 함수를 이용한 사용자수준 메모리 매핑

리눅스 프로레스는 함수들을 이용해서 가상메모리의 새로운 영역들을 만들 수 있고 객체들을 이 영역으로 매핑 가능


  1. mmap사용자 수준에서 새 가상 메모리 영역(VMA) 을 만들고, 그 영역을 파일(file-backed)이나 익명 객체(zero-fill, ZFOD2)에 매핑할 수 있다

  2. 접근 권한은 prot3, 매핑 성격은 flags 로 정한다

    • MAP_PRIVATECOW4: 쓰면 사본 생성, 원본 파일 안 바뀜
    • MAP_SHARED공유/동기화: 쓰기가 파일·다른 프로세스에 보임
    • MAP_ANONYMOUS익명(ZFOD)2: 초기 0, 파일 I/O 없이 첫 접근에 페이지 할당
  3. 지연 로딩: 매핑 순간엔 물리 메모리 안 채움. 첫 접근에 페이지 폴트
    → 파일이면 그 부분을 읽어옴, 익명이면 0으로 채운 페이지를 붙임

  4. munmap은 그 범위를 해제
    해제 후 접근은 SIGSEGV5

  5. 사용 이점: 파일을 “메모리처럼” 다루는 고성능 I/O, 라이브러리/코드 로딩, 프로세스 간 공유 메모리, 큰 데이터 처리 시 복사 최소화






  1. 프로세스 식별자 (Process Identifier) : 운영 체제에서 실행 중인 각 프로세스에 할당되는 고유한 번호 

  2. ZFOD (Zero-Fill-On-Demand): MAP_ANONYMOUS.bss/처럼 처음 접근 시 커널이 0으로 채운 새 물리 페이지를 붙이는 방식(초기엔 디스크 I/O 없음)  2

  3. prot: mmap로 만든 메모리 영역의 접근 권한 비트 

  4. COW (Copy-On-Write): MAP_PRIVATE나 fork()에서 쓰는 최적화. 처음엔 페이지를 공유/읽기전용으로 두고, 처음 쓸 때만 사본을 만들어 씀 

  5. SIGSEGV: 잘못된 주소 접근/권한 위반 시 커널이 보내는 세그멘테이션 폴트 시그널