Ai đó có thể giải thích sơ đồ này về Phân bổ Slab?


10

Tôi đang cố gắng hiểu cách phân bổ Slab hoạt động và tại sao nó khác hoặc tốt hơn so với phân trang thông thường.

Tôi tìm thấy sơ đồ này mà tôi tin rằng sẽ hữu ích nếu nó có nhiều lời giải thích hơn.

Vài câu hỏi:

  • Các mục 3KB và 7KB thể hiện điều gì? Họ phải liên quan bằng cách nào đó? Tại sao chúng được đóng gói theo cách đó?
  • Trong cột cache, bộ đệm có phải là hộp màu xám hay hộp màu trắng / xanh bên trong hộp màu xám không? Là các hộp màu xám là một gói bộ nhớ cache?
  • Là các tấm chỉ là các hộp màu xanh hoặc là toàn bộ "Trang tiếp giáp vật lý" là một tấm?

Tôi thực sự đánh giá cao sự giúp đỡ. Cảm ơn!

Phân bổ phiến

Câu trả lời:


15

Tôi có thể thấy tại sao bạn bối rối. Sơ đồ hơi khó hiểu và thực sự có thể không chính xác.

Trước hết, hãy nghĩ về lý do tại sao một hạt nhân cần một bộ cấp phát bộ nhớ dưới mức các trang. Đây có lẽ là thứ mà bạn hầu hết đều biết, nhưng tôi sẽ hoàn thành nó.

Các trang là "đơn vị" điển hình của các hoạt động bộ nhớ. Khi một ứng dụng không gian người dùng phân bổ bộ nhớ hoặc ánh xạ bộ nhớ cho một tệp hoặc một cái gì đó tương tự, nó thường có nhiều kích thước trang máy. Có một số ngoại lệ đáng chú ý; Windows sử dụng 64k làm đơn vị cấp phát bộ nhớ ảo cho dù kích thước trang của CPU là bao nhiêu. Tuy nhiên, hãy nghĩ về nó theo cách này.

Trên một CPU hiện đại, liên quan đến mã không gian người dùng, nó có một không gian địa chỉ phẳng. Đây thực sự là một ảo ảnh được cung cấp bởi hệ thống bộ nhớ ảo. HĐH cung cấp các trang từ bất kỳ nơi nào trong RAM (hoặc có thể không có RAM, trong trường hợp bộ nhớ bị hoán đổi hoặc các tệp ánh xạ bộ nhớ) và ánh xạ chúng vào một không gian địa chỉ ảo liền kề.

Điểm chính của tất cả những điều này là ngoài một vài trường hợp đặc biệt cho chính hệ điều hành (có lẽ là bộ đệm DMA, có thể một số cấu trúc dữ liệu đặc biệt được thiết lập khi khởi động, ồ và chính hình ảnh hạt nhân), hạt nhân hệ điều hành có lẽ không bao giờ phải quản lý bất kỳ khối RAM nào lớn hơn một trang. Điều này đơn giản hóa mọi thứ rất lớn, bởi vì điều đó có nghĩa là theo như các trang, mọi phân bổ và phân bổ đều có cùng kích thước. Nó cũng có hiệu quả loại bỏ sự phân mảnh bên ngoài ở cấp độ vĩ mô.

Tuy nhiên, hạt nhân cũng cần phải thực hiện một số cấu trúc dữ liệu của riêng chúng và vì thế, chúng cần một loại cấp phát bộ nhớ khác. Các cấu trúc dữ liệu này thường có thể được coi là một tập hợp các đối tượng riêng lẻ (ví dụ: một đối tượng có thể là "luồng" hoặc "mutex"). Kích thước của các đối tượng này thường nhỏ hơn nhiều so với kích thước trang.

Vì vậy, ví dụ, một đối tượng đại diện cho thông tin bảo mật của một quá trình (nghĩ về id người dùng và id nhóm trong POSIX, giả sử) chỉ có thể là 16 byte hoặc hơn, trong khi một "tiến trình" hoặc "luồng" có thể lên đến Kích thước 1kb. Rõ ràng bạn không muốn sử dụng toàn bộ trang cho các hồ sơ nhỏ này, vì vậy ý ​​tưởng là triển khai một công cụ cấp phát trên đầu trang.

Hệ thống phân bổ cấp thấp hơn phải đáp ứng nhiều vấn đề giống như phân bổ cấp trang: nó phải nhanh chóng hợp lý (bao gồm cả trên các hệ thống đa lõi), bạn muốn giảm thiểu phân mảnh, v.v. Nhưng quan trọng hơn, nó phải có thể điều chỉnh và cấu hình tùy thuộc vào loại cấu trúc dữ liệu bạn đang lưu trữ.

Một số cấu trúc dữ liệu vốn đã "giống như bộ đệm". Ví dụ, nhiều hệ điều hành duy trì bộ đệm của tên đường dẫn đến các đối tượng hệ thống tệp để tránh các chuỗi tìm kiếm thư mục dài (được gọi là "bộ đệm tên" hoặc "bộ đệm tên" trong Unix-speak). Các đối tượng này chỉ cần cho hiệu suất, không chính xác, vì vậy bạn có thể (về lý thuyết) chỉ cần quên toàn bộ trang đầy đủ các mục nếu bộ nhớ bị hạn chế và bạn cần nhanh chóng giải phóng khung hình trang.

Các cấu trúc dữ liệu khác có thể được hoán đổi vào đĩa nếu bộ nhớ bị hạn chế và bạn không cần chúng sớm. Nhưng bạn không muốn làm điều đó với các cấu trúc dữ liệu điều khiển trao đổi hoặc hệ thống bộ nhớ ảo!

Một số cấu trúc dữ liệu có thể được di chuyển xung quanh trong bộ nhớ mà không bị phạt (ví dụ: nếu không ai đề cập đến chúng bằng một con trỏ), do đó, có thể tự "thu gọn" để tránh phân mảnh nếu cần.

Vì vậy, ý tưởng chính của bộ cấp phát phiến là một trang chỉ nên lưu trữ các cấu trúc dữ liệu có cùng "loại". Điều này đánh dấu vào tất cả các ô: mỗi đối tượng trong một trang có cùng kích thước, do đó không có sự phân mảnh bên ngoài. Các đối tượng có cùng "loại" có cùng yêu cầu về hiệu suất và cùng một ngữ nghĩa.

Ngẫu nhiên, đó là một câu chuyện tương tự với phân bổ. Đối với một số loại đối tượng, có thể chờ đợi nếu không có bộ nhớ ngay lập tức để phân bổ đối tượng đó. Một đối tượng đại diện cho một tệp đang mở có thể là một ví dụ; mở một tập tin là một hoạt động tốn kém vào thời điểm tốt nhất, vì vậy chờ đợi lâu hơn một chút sẽ không làm tổn thương đến thế.

Đối với các loại đối tượng khác (ví dụ: một đối tượng đại diện cho một sự kiện thời gian thực phải xảy ra trong một thời gian nhất định kể từ bây giờ), bạn thực sự không muốn chờ đợi. Vì vậy, thật hợp lý khi một số loại đối tượng phân bổ quá mức (giả sử có một vài trang miễn phí dự trữ) để các yêu cầu có thể được thỏa mãn mà không phải chờ đợi.

Những gì bạn về cơ bản đang làm là cho phép mỗi loại đối tượng có bộ cấp phát riêng, có thể được cấu hình cho nhu cầu của đối tượng đó. Các bộ cấp phát cho mỗi đối tượng này được gọi một cách khó hiểu là "bộ nhớ cache". Bạn phân bổ một bộ đệm cho mỗi loại đối tượng. (Có, bạn cũng thường triển khai "bộ đệm của bộ đệm".) Mỗi ​​bộ đệm chỉ lưu trữ các đối tượng cùng loại (ví dụ: chỉ cấu trúc luồng hoặc chỉ cấu trúc không gian địa chỉ).

Mỗi bộ đệm, lần lượt, quản lý "tấm". Một phiến là một khung trang chứa một mảng các đối tượng cùng loại. Các tấm có thể là "đầy đủ" (tất cả các đối tượng đang sử dụng), "trống" (không có đối tượng đang sử dụng) hoặc "một phần" (một số đối tượng đang sử dụng).

Tấm một phần có lẽ là thú vị nhất, vì bộ cấp phát tấm duy trì một danh sách miễn phí cho mỗi tấm một phần. (Tấm đầy đủ và tấm trống không cần danh sách miễn phí.) Trước tiên, các đối tượng được phân bổ từ các tấm một phần (và có thể từ các tấm một phần "đầy đủ nhất") để cố gắng tránh phân bổ các trang không cần thiết.

Điều hay ho về phân bổ bản mỏng là tất cả các tùy chọn chính sách phân bổ này (cũng như ngữ nghĩa bộ nhớ) có thể được điều chỉnh cho từng loại đối tượng. Một số bộ đệm có thể giữ lại một nhóm các tấm trống và một số có thể không. Một số có thể có thể được hoán đổi sang lưu trữ thứ cấp và một số có thể không.

Linux có ba loại cấp phát bản khác nhau, tùy thuộc vào việc bạn có cần sự gọn nhẹ, thân thiện với bộ đệm hay tốc độ thô hay không. Có một bài thuyết trình tốt về điều này một vài năm trước đây giải thích sự đánh đổi tốt.

Bộ cấp phát phiến Solaris (xem bài viết để biết chi tiết ) có thêm một vài chi tiết để tăng hiệu suất hơn nữa. Để bắt đầu, trong Solaris, mọi thứ được thực hiện với phân bổ bản mỏng, bao gồm phân bổ khung trang. (Đây là giải pháp của Solaris để phân bổ các đối tượng có kích thước lớn hơn nửa trang.) Nó quản lý các đối tượng nhỏ hơn bằng cách lồng các phân bổ bản mỏng trong không gian phân bổ bản mỏng.

Một số đối tượng trong Solaris yêu cầu xây dựng và phá hủy phức tạp và tốn kém (ví dụ: các đối tượng có khóa nhân), và do đó chúng có thể "miễn phí một phần" (nghĩa là được xây dựng nhưng không được phân bổ). Solaris cũng tối ưu hóa việc phân bổ bản miễn phí bằng cách duy trì danh sách miễn phí trên cơ sở mỗi CPU, đảm bảo rằng một số hoạt động hoàn toàn không phải chờ đợi.

Để hỗ trợ phân bổ mục đích chung (ví dụ: đối với các mảng có kích thước không được biết tại thời gian biên dịch), hầu hết các hệ điều hành kiểu macrokernel cũng có bộ đệm đại diện cho kích thước đối tượng thay vì loại đối tượng . Ví dụ, FreeBSD duy trì bộ nhớ cache cho các đối tượng không xác định có kích thước là 2 byte, từ 4 đến 256.

Những gì tôi hy vọng bạn có thể thấy là phân bổ bản mỏng là một khung rất linh hoạt có thể được điều chỉnh cho các nhu cầu của các loại dữ liệu khác nhau. Nó không cạnh tranh với phân trang, nhưng bổ sung cho nó (mặc dù trong Solaris, các khung trang được phân bổ bằng các tấm).

Tôi hi vọng cái này giúp được. Hãy cho tôi biết nếu có bất cứ điều gì cần làm rõ.


6

Ý tưởng bên dưới bộ cấp phát bản là hệ điều hành cần các cấu trúc dữ liệu cụ thể nhưng hơi chuẩn (ví dụ: quy trình PCB, semaphores, siêu dữ liệu tệp, v.v.) gợi ý việc sử dụng bộ nhớ cần thiết cho chúng.

Thuật toán cấp phát bản sàn cung cấp các kho của các vùng nhớ có kích thước và khởi tạo được tối ưu hóa cho các cấu trúc dữ liệu tiêu chuẩn này. Ví dụ, như bạn có thể thấy từ hình ảnh, có thể tồn tại các đối tượng 3kb cũng như của các đối tượng 7kb. Tuy nhiên, chúng ta biết rằng kernel chỉ phân bổ bộ nhớ theo bội số của kích thước trang.

Để tránh lãng phí thời gian và bộ nhớ, HĐH giữ trong các vùng bộ nhớ cache khác nhau có thể được phân bổ nhanh chóng theo yêu cầu và kích thước bộ đệm khác nhau cho mọi loại đối tượng và cấu trúc. Tuy nhiên, bộ nhớ cache không trực tiếp chứa và quản lý các vùng nhớ này và thậm chí không được đảm bảo nằm trong bộ nhớ liền kề. Thay vào đó, chúng được chia thành các phiến, các trang bộ nhớ liền kề, có số lượng thường được chọn để giảm sự phân mảnh bộ nhớ. Đó là trong bản sàn nằm trong các trường hợp đối tượng khác nhau, cho dù được phân bổ hay miễn phí. Nếu bộ đệm đầy, bản mới được phân bổ ở đâu đó trong bộ nhớ chính và nó được thêm vào bộ đệm.

Tóm lại, những thứ bạn có thể nhìn thấy trong hình là những ví dụ về các đối tượng mà HĐH biết là 3 - bất kể kB lớn là gì. Hạt nhân không phân bổ bộ nhớ trang dành riêng cho chúng, vì điều đó sẽ tăng phân mảnh bộ nhớ theo cấp số nhân, nhưng "chuyển hướng" chúng vào bộ đệm (hộp màu xám). Trong bộ đệm nên có các địa chỉ chỉ ra các vùng tiếp giáp vật lý, các tấm (bộ hộp trắng / xanh) và các đối tượng cuối cùng được phân bổ trong một khu vực của tấm (một phần có màu xanh lam, không có màu xanh khu vực bộ nhớ tương tự đầy đủ của cùng một tấm).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.