Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] Mô phỏng cấp phát bộ nhớ theo hệ thống buddy

    Hệ thống buddy (buddy system) là một kỹ thuật cấp phát bộ nhớ cổ điển: toàn bộ vùng nhớ có kích thước MMM (với MMM là lũy thừa của 222) được xem như một khối duy nhất ở "mức" k=log⁡2Mk=\log_2 Mk=log2​M. Một khối ở mức ℓ\ellℓ có kích thước 2ℓ2^\ell2ℓ và có thể được tách (split) thành hai khối "buddy" bằng nhau ở mức ℓ−1\ell-1ℓ−1; ngược lại, hai khối buddy cùng mức đang trống có thể được gộp (merge) trở lại thành một khối ở mức cao hơn. Hai khối kích thước 2ℓ2^\ell2ℓ tại địa chỉ a và a XOR 2^\ell luôn là buddy của nhau.

    • ALLOC id n: gọi sz=2ℓsz=2^\ellsz=2ℓ là lũy thừa của 222 nhỏ nhất thỏa sz≥nsz \ge nsz≥n (yêu cầu sz≤Msz \le Msz≤M, nếu không cấp phát thất bại). Tìm khối trống nhỏ nhất có kích thước ≥sz\ge sz≥sz (ưu tiên mức thấp nhất có khối trống, và trong mức đó chọn khối có địa chỉ nhỏ nhất); nếu không có khối trống nào đủ lớn, thất bại. Nếu khối tìm được lớn hơn szszsz, tách liên tiếp thành hai buddy bằng nhau cho tới khi đạt đúng mức ℓ\ellℓ: mỗi lần tách, nửa có địa chỉ lớn hơn được đưa vào danh sách khối trống ở mức thấp hơn, nửa còn lại (địa chỉ nhỏ hơn) tiếp tục được xét/tách. Khối cuối cùng kích thước szszsz được gán cho id.
    • FREE id: giải phóng khối của id (kích thước 2ℓ2^\ell2ℓ tại địa chỉ a); sau đó gộp lặp lại: nếu buddy của khối (địa chỉ a XOR 2^\ell) đang trống và cùng mức ℓ\ellℓ, gộp thành khối kích thước 2ℓ+12^{\ell+1}2ℓ+1 tại địa chỉ min⁡(a,buddy)\min(a, \text{buddy})min(a,buddy), rồi tiếp tục thử gộp ở mức cao hơn, cho tới khi không thể gộp nữa hoặc đã đạt mức kkk.

    Phần chênh lệch sz−nsz - nsz−n của mỗi lần cấp phát thành công gọi là phân mảnh nội bộ (internal fragmentation) của khối đó.

    Ví dụ: M=64M=64M=64 (k=6k=6k=6), các lệnh ALLOC A 10, ALLOC B 20, ALLOC C 5, FREE B, ALLOC D 8, FREE A:

    • A 10→sz=16\to sz=16→sz=16: tách khối 646464 thành 32+3232+3232+32 rồi tách nửa 323232 thành 16+1616+1616+16; cấp AAA tại địa chỉ 000 (kích thước 161616); còn trống: mức 555 có {32}\{32\}{32}, mức 444 có {16}\{16\}{16}.
    • B 20→sz=32\to sz=32→sz=32: dùng luôn khối trống 323232 tại địa chỉ 323232; cấp tại 323232 (kích thước 323232).
    • C 5→sz=8\to sz=8→sz=8: tách khối 161616 tại 161616 thành 8+88+88+8; cấp CCC tại 161616 (kích thước 888); còn trống mức 333: {24}\{24\}{24}.
    • FREE B: buddy của (32,32)(32,32)(32,32) là địa chỉ 000 ở mức 555 — không trống (đang là hai khối con) nên không gộp; khối 323232 trở lại trống.
    • D 8→sz=8\to sz=8→sz=8: dùng khối trống 888 tại 242424; cấp tại 242424.
    • FREE A: buddy của (0,16)(0,16)(0,16) là địa chỉ 161616 ở mức 444 — không trống (đã tách) nên không gộp; khối 161616 tại 000 trở lại trống.

    Cuối cùng còn trống: khối 161616 tại 000 và khối 323232 tại 323232, tổng 484848 byte, 222 khối. Các đối tượng còn đang cấp phát: CCC (mức 333, kích thước 888, phân mảnh 8−5=38-5=38−5=3) và DDD (kích thước 888, phân mảnh 000); tổng phân mảnh nội bộ hiện tại là 333.

    • Định dạng đầu vào:

      Dòng đầu tiên gồm hai số nguyên MMM và mmm (MMM là lũy thừa của 222, 1≤M≤2301 \le M \le 2^{30}1≤M≤230, 0≤m≤20000 \le m \le 20000≤m≤2000).

      mmm dòng tiếp theo, mỗi dòng là ALLOC id n (id là token không chứa khoảng trắng, 1≤n≤M1 \le n \le M1≤n≤M) hoặc FREE id.

    • Định dạng đầu ra:

      Với mỗi lệnh ALLOC, in ra một dòng: addr size (địa chỉ và kích thước 2ℓ2^\ell2ℓ thực tế được cấp) nếu thành công, hoặc -1 nếu thất bại.

      Sau đó in thêm 333 dòng phản ánh trạng thái khi kết thúc chương trình:

      • Tổng số byte còn trống trong toàn bộ hệ thống buddy.
      • Tổng số khối trống hiện có (ở mọi mức).
      • Tổng phân mảnh nội bộ của tất cả các đối tượng hiện đang được cấp phát (chưa FREE).

    Ví dụ:

    Đầu vào:

    16 0
    

    Đầu ra:

    16
    1
    0
    

    Đầu vào:

    64 6
    ALLOC A 10
    ALLOC B 20
    ALLOC C 5
    FREE B
    ALLOC D 8
    FREE A
    

    Đầu ra:

    0 16
    32 32
    16 8
    24 8
    48
    2
    3
    

    Đang tải editor...