Skip to content

Zoom-in: Virtual Memory

Karify98·
Cover Image for Zoom-in: Virtual Memory

Chạy nhiều ứng dụng nặng cùng lúc trên máy tính, mỗi ứng dụng đều tự tin truy cập vào các địa chỉ bộ nhớ từ thấp đến cao như thể nó là chương trình duy nhất đang chạy trên hệ thống.

graph TD
    App1["💻 App 1 (Chrome)"] -->|"Đọc địa chỉ 0x7FFF"| VM["🧠 Bộ nhớ RAM vật lý"]
    App2["💻 App 2 (VS Code)"] -->|"Ghi địa chỉ 0x7FFF"| VM
    style App1 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style App2 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style VM fill:#1a3a2a,stroke:#22c55e,color:#86efac

Phóng to dần vào đó.


Layer 1 — Logical vs. Physical Address: Tách biệt địa chỉ ảo và thật

Nếu các chương trình ghi dữ liệu trực tiếp vào địa chỉ RAM vật lý, một lỗi nhỏ của ứng dụng này (bug ghi đè bộ nhớ) có thể ghi đè lên dữ liệu của ứng dụng khác hoặc phá hỏng hệ điều hành.

Hệ điều hành giải quyết việc này bằng một abstraction gọi là địa chỉ ảo (logical/virtual address).

graph LR
    App["💻 Ứng dụng"] -->|"Địa chỉ ảo: 0x4000"| MMU["🧠 MMU (Hardware)"]
    MMU -->|"Dịch sang địa chỉ vật lý: 0x1A20"| RAM["📋 RAM vật lý"]
    style App fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style MMU fill:#3b2a1a,stroke:#f59e0b,color:#fcd34d
    style RAM fill:#1a3a2a,stroke:#22c55e,color:#86efac

Ứng dụng chỉ nhìn thấy địa chỉ ảo. Khi ứng dụng thực hiện đọc/ghi dữ liệu, bộ quản lý bộ nhớ phần cứng MMU (Memory Management Unit) của CPU sẽ dịch địa chỉ ảo đó sang địa chỉ vật lý thật trên thanh RAM. Mỗi ứng dụng có một bản đồ dịch địa chỉ hoàn toàn khác nhau, đảm bảo chúng không bao giờ có thể can thiệp hay đọc trộm bộ nhớ của nhau.

Vấn đề còn lại: ánh xạ từng byte địa chỉ một sẽ làm bản đồ ánh xạ trở nên khổng lồ, ngốn sạch toàn bộ RAM chỉ để lưu thông tin ánh xạ.

Layer 2 — Paging: Chia bộ nhớ thành các trang 4KB

Thay vì ánh xạ từng byte đơn lẻ, hệ điều hành chia bộ nhớ thành các khối có kích thước cố định gọi là các trang bộ nhớ (Pages ở phía ảo) và các khung trang (Frames ở phía vật lý). Kích thước tiêu chuẩn thường là 4KB.

graph TD
    subgraph Virtual Address Space (App)
        P1["Page 1"]
        P2["Page 2"]
        P3["Page 3"]
    end
    subgraph Page Table (Bản đồ)
        PT["Ánh xạ Page -> Frame"]
    end
    subgraph Physical RAM
        F2["Frame 2 (đang chứa Page 1)"]
        F5["Frame 5 (đang chứa Page 2)"]
        F1["Frame 1 (đang chứa Page 3)"]
    end

    P1 --> PT --> F2
    P2 --> PT --> F5
    P3 --> PT --> F1

    style P1 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style P2 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style P3 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style PT fill:#3b2a1a,stroke:#f59e0b,color:#fcd34d
    style F2 fill:#1a3a2a,stroke:#22c55e,color:#86efac
    style F5 fill:#1a3a2a,stroke:#22c55e,color:#86efac
    style F1 fill:#1a3a2a,stroke:#22c55e,color:#86efac

Bản đồ ánh xạ lúc này được gọi là Page Table. Nhờ cơ chế này, hệ điều hành có thể phân bổ các trang bộ nhớ của một ứng dụng nằm rải rác bất kỳ đâu trên RAM vật lý mà không bắt buộc chúng phải nằm liên tục nhau. Việc này loại bỏ hoàn toàn hiện tượng phân mảnh bộ nhớ (external fragmentation).

Vấn đề còn lại: tổng dung lượng bộ nhớ ảo mà tất cả các app đang dùng có thể vượt quá dung lượng vật lý của thanh RAM lắp trên máy.

Layer 3 — Page Fault & Swap: Vượt giới hạn vật lý của RAM

Virtual Memory cho phép hệ thống sử dụng ổ cứng (SSD hoặc HDD) làm phần mở rộng của RAM qua cơ chế trao đổi (Swap).

sequenceDiagram
    participant App as 💻 Ứng dụng
    participant CPU as 🧠 CPU / MMU
    participant OS as 🖥️ Hệ điều hành (Kernel)
    participant Disk as 💾 Ổ cứng (Swap)
    participant RAM as 📋 RAM vật lý

    App->>CPU: 1. Đọc dữ liệu tại Page 4
    CPU-->>CPU: 2. Kiểm tra Page Table: Trạng thái Present Bit = 0 (Chưa có trên RAM)
    Note over CPU: Kích hoạt ngắt Page Fault!
    CPU->>OS: 3. Báo động lỗi Page Fault
    OS->>Disk: 4. Đọc dữ liệu của Page 4 từ Swap file
    Disk-->>OS: 5. Trả về dữ liệu
    OS->>RAM: 6. Ghi dữ liệu vào một Frame trống trên RAM
    OS-->>CPU: 7. Cập nhật Page Table (Present Bit = 1)
    CPU-->>App: 8. Tiếp tục thực thi câu lệnh đọc bộ nhớ thành công

Khi ứng dụng yêu cầu đọc dữ liệu từ một trang ảo chưa được tải vào RAM vật lý, CPU sẽ phát hiện thuộc tính trạng thái (present bit) bằng không và phát ra một ngắt hệ thống gọi là Page Fault.

Lúc này, hệ điều hành (Kernel) tạm dừng ứng dụng, tìm một vùng trống trên RAM vật lý (nếu RAM đầy, nó sẽ đẩy một trang khác ít dùng của ứng dụng khác xuống ổ cứng để giải phóng chỗ trống), tải dữ liệu của trang đang cần từ phân vùng Swap trên SSD lên RAM, cập nhật lại Page Table, rồi cho phép CPU tiếp tục chạy câu lệnh của ứng dụng như chưa hề có chuyện gì xảy ra.


Full picture

graph TD
    subgraph Bộ nhớ ảo (Virtual Address Space)
        V1["Page 1 (Active)"]
        V2["Page 2 (Active)"]
        V3["Page 3 (Idle)"]
        V4["Page 4 (Active)"]
    end

    subgraph Memory Translation & Management
        PT["Page Table\n(Dịch địa chỉ & Quản lý trạng thái)"]
        MMU["CPU MMU\n(Kiểm tra Present Bit)"]
    end

    subgraph RAM vật lý
        R1["Frame A (đang chứa Page 1)"]
        R2["Frame B (đang chứa Page 2)"]
        R3["Frame C (đang chứa Page 4)"]
    end

    subgraph Ổ cứng (Disk Swap Space)
        S1["Swap block (chứa dữ liệu Page 3)"]
    end

    V1 --> PT
    V2 --> PT
    V3 --> PT
    V4 --> PT

    PT --> MMU
    MMU -->|"Present = 1"| R1
    MMU -->|"Present = 1"| R2
    MMU -->|"Present = 1"| R3
    MMU -->|"Present = 0 (Page Fault)"| S1

    style V1 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style V2 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style V3 fill:#1e293b,stroke:#334155,color:#94a3b8
    style V4 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style PT fill:#3b2a1a,stroke:#f59e0b,color:#fcd34d
    style MMU fill:#3b2a1a,stroke:#f59e0b,color:#fcd34d
    style R1 fill:#1a3a2a,stroke:#22c55e,color:#86efac
    style R2 fill:#1a3a2a,stroke:#22c55e,color:#86efac
    style R3 fill:#1a3a2a,stroke:#22c55e,color:#86efac
    style S1 fill:#1e293b,stroke:#475569,color:#cbd5e1

Takeaway

Bộ nhớ ảo là nền tảng cốt lõi giúp các hệ điều hành đa nhiệm vận hành ổn định. Nó không chỉ đơn thuần là bộ đệm khi thiếu RAM vật lý, mà còn là vách ngăn bảo vệ, cách ly không gian dữ liệu giữa các tiến trình ứng dụng. Khi bạn cấu hình giới hạn tài nguyên (RAM limit) cho container bằng các công cụ như Docker hay Kubernetes thông qua cgroups, thực chất là bạn đang thiết lập trần phân bổ trang ảo ở tầng nhân hệ điều hành.


Bài viết được hỗ trợ bởi Amy 🌸 - AI Assistant. Nội dung đã được kiểm duyệt bởi tác giả.

Related Posts