Đơn vị quản lý bộ nhớ

Đơn vị quản lý bộ nhớ (MMU), hay còn gọi là trang quản lý bộ nhớ (PMMU) là một thiết bị phần cứng chứa tất cả những tham chiếu của bộ nhớ đã đi qua nó hỗ trợ việc ánh xạ từ địa chỉ bộ nhớ ảo ra địa chỉ bộ nhớ vật lý. Bộ phận này thường được tích hợp vào CPU, nhưng đôi lúc nó cũng có thể là một mạch tích hợp riêng biệt.

Đơn vị quản lý bộ nhớ là một cách  thực hiện quản lý bộ nhớ ảo rất hiệu quả. Nó xử lý tại cùng lúc  với việc bảo vệ bộ nhớ, quản lý bộ nhớ đệm, bộ điều khiển xung, và trong kiến trúc máy tính đơn giản (đặc biệt là hệ thống 8-bit), là việc chuyển khối.

== Tổng quan ==
Những đơn vị quản lý bộ nhớ hiện đại thường phân chia không gian cho địa chỉ ảo (khu vực địa chỉ ô nhớ được sử dụng bởi bộ vi xử lý) vào các trang mà mỗi trang có kích thước là lũy thừa của 2, thường là một vài kilobyte, nhưng cũng có thể lớn hơn rất nhiều. Khu vực dưới của địa chỉ thường không đổi còn khu vực trên là những số trang ảo.

=== Page Table Entries (PTEs) ===
Đa số đơn vị quản lý bộ nhớ (MMU) sử dụng một bảng của các "mục" trong bộ nhớ (in-memory table ?) được gọi là "bảng trang", chứa mỗi "page table entry" mỗi bảng, để ánh xạ từ trang ảo tới trang thực trong bộ nhớ chính. Một bộ nhớ đệm liên kết của PTEs được gọi là translation lookaside buffer (TLB) và được sử dụng để tránh sự cần thiết truy cập bộ nhớ chính mỗi lần địa chỉ ảo được ánh xạ. Một số đơn vị quản lý bộ nhớ khác có thế có mảng riêng tư của bộ nhớ hoặc những thanh ghi giữ những cặp PTEs. "Số trang thực" (Physical Page Number) ghép với "trang bù thêm" (Page Offset) được địa chỉ thực (Physical address) hoàn chỉnh.

Một PTE có thể bao gồm thông tin khi nào trang đã được viết (dirty bit), lần cuối được sử dụng (Least Recently Used (LRU) ), loại tiến trình được viết hay đọc, và khi nào nó được "cached".

Thỉnh thoảng, một PTE ngăn cản truy cập vào trang ảo, bởi vì không có RAM thực (physical RAM ?) được cấp phép vào trang ảo đó. Trong trường hợp này đơn vị quản lý bộ nhớ gửi tính hiệu "Page fault" tới  bộ vi xử lý trung tâm (CPU). Sau đó hệ điều hành (OS) xử lý tình huống bằng cách tìm một "khung thay thế" (spare frame) của RAM và cài đặt một PTE mới ánh xạ tới địa chỉ ảo được yêu cầu. Nếu như RAM không còn dư, thì cần thiết để chọn một trang đang tồn tại (được biết tới là "nạn nhân" (victim)), sử dụng một số thuật toán thay thế, và lưu nó trong "disk" (tiến trình này được gọi là "paging"). Với một số đơn vị quản ly bộ nhớ có thể xảy ra tình trạng thiếu hụt PTEs, trong trường hợp này hệ điều hành phải giải phóng một để tạo nên một ánh xạ mới.

Một đơn vị quản lý bộ nhớ có thể gây ra lỗi truy cập điều kiện không hợp lý (illegal access error conditions) hoặc "Page fault" không tồn tại bởi vì truy cập địa chỉ sai hoặc không tồn tại, tương ứng dẫn đến một số lỗi liên quan đến bộ nhớ như segmentation fault hoặc bus error bởi hệ điều hành.

=== Lợi ích ===
Trong nhiều trường hợp, không tìm thấy trang nhớ có thể gây ra lỗi phầm mềm. Điều này có thể được ngăn chặn bằng các sử dụng khả năng bạo vệ bộ nhớ, vốn là một lợi ích của đơn vị quản lý bộ nhớ: hệ điều hành có thể dùng MMU để chống lại các phần mềm độc hại bằng cách không cho các phần mềm này sử dụng các vùng nhớ mà đáng lý ra nó không được đụng tới.

MMU cũng được dùng để phân vùng bộ nhớ. Sau khi được cho mược hoặc trả lại, các vùng của bộ nhớ có thể bị chia cắt sao cho các vùng nhớ lớn và liên tục có thể bị ép lại nhỏ hơndung lượng của chúng. Với bộ nhớ ảo, một chuỗi dữ liệu liên tục có thể được tách ra thành nhiều chuỗi dữ liệu không liên tục trong bộ nhớ vật lý.

== Một số ví dụ ==
=== IA-32/x86 ===
Các kiến trúc x86 đã phát triển qua một thời gian rất dài, trong khi phải duy trì khả năng tương thích phần mềm đầy đủ, thậm chí với những bộ mã hệ điều hành khác nhau. Cùng với đó, đơn vị quản lý bộ nhớ trở nên vô cùng phức tạp, với nhiều chế độ hoạt động khác nhau. Cơ chế hoạt động của bộ xử lý 80386(một trong những bộ xử lý đầu tiên sở hữu kiến trúc x86) và những cải tiến của nó được mô tả trong phần này.

Bộ xử lý chia bộ nhớ thành các trang gồm 4KB dữ liệu. Các thanh ghi phân đoạn, được dựa trên các thiết kế bộ quản lý bộ nhớ của các bộ xử lý cũ 8088 và 80286 của Intel, không còn được sử dụng trong các hệ điều hành hiện đại, nhưng với một ngoại lệ: truy cập vào các luồng dữ liệu cho các ứng dụng máy tính và các dữ liệu đặc biệt của bộ xử lý trung tâm cho nhân(kernel) hệ điều hành, việc mà các thanh ghi phân đoạn FS và GS làm rất tốt. Mọi hoạt động truy cập bộ nhớ được thực hiện bởi một thanh ghi do mã đang thực thi quyết định. Các thanh ghi phân đoạn đại diện của một bảng dữ liệu, bảng dữ liệu này cung cấp một khoảng trống để cộng vào trong các địa chỉ bộ nhớ ảo. Trừ khi sử dụng các FS và GS, hệ điều hành sẽ ngầm hiểu phần khoảng trống này có giá trị là 0.

Sau khi được thêm vào khoảng trống, mỗi giá trị bộ nhớ không dài quá 32bits. Kết quả của việc này có thể được mô tả như một bảng dạng cây, với địa chỉ được chia làm 3 phần: 10 bits mô tả nhánh nào trong cây, 10 bits mô tả địa chỉ ở lá nào của nhánh và 12 bits còn lại được sao chép vào kết quả. Với một số hệ điều hành thuộc họ Unix như OpenBSD hoặc Linux thì có thể giới hạn độ dài của các đoạn mã này một cách riêng biệt do các thanh ghi phân mảnh CS quyết định, để tránh việc cho phép thực thi một đoạn mã “lạ” nằm trong phần bộ nhớ có thể chỉnh sửa.

Một số hiệu chỉnh nhỏ trong bộ quản lý bộ nhớ được giới thiệu với các bộ vi xử lý nổi tiếng của Intel là Pentium cho phép một trang nhớ rất lớn lên tới 4MB so với trước kia là 4KB bằng cách bỏ qua các cấp thấp của mô hình cây.

Với bộ vi xử lý mới Pentium Pro, Intel tiếp tục cải tiến bộ quản lý bộ nhớ với tính năng mở rộng địa chỉ vật lý. Thay vì 32bits như trước đây, ta có thể mở rộng các địa chỉ lên tới 36bits thông qua một bảng gồm 3 tầng: với 9 + 9 + 2 bits cho 3 tầng và vẫn là 12bits cho kết quả, một trang lớn với dung lượng 2MB. Ngoài ra các bảng cho phép tối ưu hóa khả năng đưa vào bộ nhớ đệm bằng cách tìm kiếm trên một vùng nhớ nhỏ trên bộ vi xử lý.

=== x86-64 ===
x86-64 là một phần mở rộng 64-bit của x86 mà gần như hoàn toàn loại bỏ các thanh ghi đoạn có lợi cho các mô hình bộ nhớ phẳng được sử dụng bởi hầu như tất cả các hệ điều hành cho x86 hoặc vi xử lý mới hơn. Trong Long Mode, tất cả offset thanh ghi đoạn được bỏ qua, trừ các thanh ghi đoạn FS và GS. Khi được sử dụng với 4KB trang nhớ, bảng cây trang nhớ có bốn cấp độ thay vì ba.

Các địa chỉ ảo được phân chia như sau: 16 bit không sử dụng, 9 bit cho mỗi bốn cấp cây (tổng cộng là 36 bit), và 12 bit thấp nhất sao chép trực tiếp đến kết quả. Với 2MB trang nhớ, chỉ có ba cấp độ của bảng trang nhớ, với tổng số 27 bit được sử dụng trong phân trang nhớ và 21 bit của offset. Một số CPU mới hơn cũng hỗ trợ một 1 GB trang nhớ với hai mức độ phân trang và 30 bit của offset.
CPUID có thể được sử dụng để xác định xem 1GB trang nhớ được hỗ trợ. Trong cả ba trường hợp, 16 bit cao nhất phải có bằng với bit thứ 48, hay nói cách khác, 48 bit thấp là dấu hiệu mở rộng đến các bit cao hơn. Điều này được thực hiện để cho phép mở rộng của các phạm vi địa chỉ trong tương lai mà không ảnh hưởng tới tính tương thích ngược. Trong tất cả các cấp của bảng trang nhớ, mục bảng trang nhớ bao gồm 1bit không thực thi.

==== Điểm lợi của vi xử lý 64-bit ====
- Với phép tính dài, bạn sẽ thực hiện nhanh gấp đôi như ví dụ phép tính 12 + 34 ở trên.
- CPU sẽ có thể truy cập được nhiều địa chỉ trên RAM hơn. Điều này đã tỏ ra hữu ích trong bối cảnh máy tính giờ đây đã có nhiều model sử dụng 6GB, thậm chí là 8GB và 16GB RAM. Trong thời gian tới, thiết bị di động rồi cũng sẽ được trang bị RAM trên 4GB và đó là lúc vi xử lý 64-bit trở thành điều bắt buộc.
- Ngoài tra, tranh thủ việc thay đổi kiến trúc lên 64-bit, số lượng register và số lượng câu lệnh chỉ dẫn (instructions) cũng được tăng lên. Về số lượng thanh ghi thì như ví dụ ở trên, nếu bạn chỉ có 3 thanh ghi, sau khi thực hiện câu lệnh xong thì bạn sẽ phải xoá dữ liệu trên thanh ghi đó để có thể tiếp tục thực hiện phép tính khác. Nếu sau đó bạn có phép tính gì đến biến c chẳng hạn bạn sẽ phải lại gọi bus chở dữ liệu lại cho bạn, mất thời gian hơn. Còn nếu có nhiều thanh ghi, bạn cứ để tạm những cái biến kia ở đó để sau này dùng lại cũng được.
- Lợi ích của việc tăng số lượng câu lệnh: ví dụ như chip của bạn chỉ có câu lệnh thực hiện phép cộng. Khi đó bốn phép tính 3+3+3+3 bạn sẽ phải chạy câu lệnh (+) 3 lần. Nếu máy tính của bạn có câu lệnh nhân, bạn chỉ cần chạy 1 lệnh 3x4 là xong. (Tuy nhiên, bản thân chip di động đã là giản lược rất nhiều câu lệnh so với chip máy tính. Nên dù tăng thêm số câu lệnh, độ dài câu lệnh vẫn ko thay đổi, vẫn là 32 bit.)