Sự khác biệt giữa vmalloc và kmalloc là gì?


113

Tôi đã tìm kiếm xung quanh và nhận thấy hầu hết mọi người ủng hộ việc sử dụng kmalloc, vì bạn được đảm bảo nhận được các khối bộ nhớ vật lý liền kề. Tuy nhiên, nó cũng có vẻ như kmalloccó thể thất bại nếu không tìm thấy khối vật lý liền kề mà bạn muốn.
Lợi thế của việc có một khối bộ nhớ liền kề là gì? Cụ thể, tại sao tôi cần có một khối bộ nhớ vật lý liền kề trong một lệnh gọi hệ thống ? Có lý do gì tôi không thể sử dụng vmalloc?
Cuối cùng, nếu tôi cấp phát bộ nhớ trong quá trình xử lý lệnh gọi hệ thống, tôi có nên chỉ định GFP_ATOMICkhông? Một lệnh gọi hệ thống có được thực thi trong ngữ cảnh nguyên tử không?

GFP_ATOMIC
Việc phân bổ là ưu tiên cao và không ngủ. Đây là lá cờ để sử dụng trong trình xử lý ngắt, nửa dưới và các tình huống khác mà bạn không thể ngủ.

GFP_KERNEL Đây là một phân bổ bình thường và có thể bị chặn. Đây là cờ để sử dụng trong mã ngữ cảnh quy trình khi nó an toàn ở chế độ ngủ.



4
Bài báo đó tuyên bố vô nghĩa như: "Nói chung kiến ​​trúc 32 bit có kích thước trang 4KB và kiến ​​trúc 64 bit có kích thước trang 8KB". Tôi chưa đọc hết nó, nhưng tôi sẽ không gọi nó là "hay", hay thậm chí tin tưởng một từ nào đó từ nó.
Alexandro Sánchez

1
Lưu ý (bán liên quan): vmallocnhanh hơn với Kernel 5.2 (Quý 2 năm 2019)
VonC

Câu trả lời:


96

Bạn chỉ cần lo lắng về việc sử dụng bộ nhớ liền kề vật lý nếu bộ đệm sẽ được truy cập bởi thiết bị DMA trên một bus địa chỉ vật lý (như PCI). Rắc rối là nhiều lệnh gọi hệ thống không có cách nào để biết liệu bộ đệm của chúng cuối cùng có được chuyển đến thiết bị DMA hay không: một khi bạn chuyển bộ đệm cho một hệ thống con hạt nhân khác, bạn thực sự không thể biết nó sẽ đi đâu. Ngay cả khi hạt nhân không sử dụng bộ đệm cho DMA ngày hôm nay, một sự phát triển trong tương lai có thể làm như vậy.

vmalloc thường chậm hơn kmalloc, vì nó có thể phải tạo lại không gian đệm thành một phạm vi gần như liền kề. kmalloc không bao giờ remaps, mặc dù nếu không được gọi bằng GFP_ATOMIC, kmalloc có thể chặn.

kmalloc bị giới hạn về kích thước bộ đệm mà nó có thể cung cấp: 128 KBytes *) . Nếu bạn cần một bộ đệm thực sự lớn, bạn phải sử dụng vmalloc hoặc một số cơ chế khác như dự trữ bộ nhớ cao khi khởi động.

*) Điều này đúng với các hạt nhân trước đó. Trên các hạt nhân gần đây (tôi đã kiểm tra điều này trên 2.6.33.2), kích thước tối đa của một kmalloc duy nhất là 4 MB! (Tôi đã viết một bài khá chi tiết về điều này .) - kaiwan

Đối với cuộc gọi hệ thống, bạn không cần phải chuyển GFP_ATOMIC tới kmalloc (), bạn có thể sử dụng GFP_KERNEL. Bạn không phải là một trình xử lý ngắt: mã ứng dụng đi vào ngữ cảnh hạt nhân bằng một cái bẫy, nó không phải là một ngắt.


1
Tôi nghĩ rằng các lệnh gọi hệ thống đã được nhập bằng cách kích hoạt int $ 0x80? (tức là ngắt)?
FreeMemory 22/09/08

2
int $ 0x80 là một ngắt phần mềm, còn được gọi là một cái bẫy. Ý nghĩa của các trình xử lý ngắt là một ngắt phần cứng, chẳng hạn như khi người dùng nhấn một phím hoặc di chuyển các bước di chuyển.
Branan 22/09/08

Lời gọi hệ thống dành cho không gian người dùng để chuyển đổi không gian hạt nhân ... kmalloc chỉ được sử dụng trong ngữ cảnh hạt nhân ??
AIB

3
@FreeMemory: int $ 0x80 dành riêng cho x86 và sau đó, nó cũng là một phương pháp cũ được thay thế bởi sysenter / syscall (trên x86).
jørgensen

18

Câu trả lời ngắn gọn: tải xuống Trình điều khiển thiết bị Linux và đọc chương về quản lý bộ nhớ.

Nghiêm túc mà nói, có rất nhiều vấn đề tế nhị liên quan đến quản lý bộ nhớ nhân mà bạn cần hiểu - Tôi đã dành rất nhiều thời gian để gỡ lỗi các vấn đề với nó.

vmalloc () rất hiếm khi được sử dụng, vì hạt nhân hiếm khi sử dụng bộ nhớ ảo. kmalloc () là cái thường được sử dụng, nhưng bạn phải biết hậu quả của các cờ khác nhau là gì và bạn cần một chiến lược để đối phó với những gì xảy ra khi nó không thành công - đặc biệt nếu bạn đang ở trong một trình xử lý ngắt, như bạn đã đề xuất.


1
"bởi vì hạt nhân hiếm khi sử dụng bộ nhớ ảo", tại sao lại như vậy?
Trey

Bởi vì bạn thường không muốn khối hạt nhân trong khi chờ kernel vào bộ nhớ swap trong hoặc ra khỏi đĩa lưu trữ ...
Mike Heinz

Không, bộ nhớ hạt nhân được cấp phát bằng vmalloc không bao giờ được hoán đổi. Chỉ có thể hoán đổi bộ nhớ không gian người dùng. Không gian địa chỉ hạt nhân là không thể thay đổi được và vmalloc phân bổ trong không gian địa chỉ của hạt nhân.
user2679859

13

Phát triển nhân Linux của Robert Love (Chương 12, trang 244 trong ấn bản thứ 3) giải đáp điều này rất rõ ràng.

Có, bộ nhớ liền kề vật lý là không cần thiết trong nhiều trường hợp. Lý do chính để kmalloc được sử dụng nhiều hơn vmalloc trong kernel là hiệu suất. Cuốn sách giải thích, khi các khối bộ nhớ lớn được cấp phát bằng vmalloc, hạt nhân phải ánh xạ các khối (trang) vật lý không liền kề thành một vùng bộ nhớ ảo liền kề duy nhất. Vì bộ nhớ hầu như liền kề và không tiếp giáp về mặt vật lý, một số ánh xạ địa chỉ ảo-vật lý sẽ phải được thêm vào bảng trang. Và trong trường hợp xấu nhất, sẽ có (kích thước của bộ đệm / kích thước trang) số lượng ánh xạ được thêm vào bảng trang.

Điều này cũng tạo thêm áp lực lên TLB (các mục trong bộ đệm lưu trữ các ánh xạ địa chỉ ảo sang vật lý gần đây) khi truy cập bộ đệm này. Điều này có thể dẫn đến đập .


11

Các kmalloc()& vmalloc()chức năng là một giao diện đơn giản để đạt được bộ nhớ hạt nhân trong khối byte kích thước.

  1. Các kmalloc()chức năng đảm bảo rằng các trang có thể chất tiếp giáp (và hầu như liền kề).

  2. Các vmalloc()chức năng làm việc trong một thời trang tương tự như kmalloc(), ngoại trừ nó cấp phát bộ nhớ mà chỉ hầu như tiếp giáp và không nhất thiết thể chất tiếp giáp.


4

Lợi ích của việc có một khối bộ nhớ liền kề là gì? Cụ thể, tại sao tôi cần có một khối bộ nhớ vật lý liền kề trong một lệnh gọi hệ thống? Có lý do gì tôi không thể chỉ sử dụng vmalloc?

Từ "Tôi cảm thấy may mắn" của Google trên vmalloc:

kmalloc là cách ưa thích, miễn là bạn không cần diện tích quá lớn. Vấn đề là, nếu bạn muốn thực hiện DMA từ / đến một số thiết bị phần cứng, bạn sẽ cần sử dụng kmalloc và có thể bạn sẽ cần đoạn lớn hơn. Giải pháp là cấp phát bộ nhớ càng sớm càng tốt, trước khi bộ nhớ bị phân mảnh.


Thấy chưa, tôi đã đọc nó, và nó không có ý nghĩa gì đối với tôi. Tôi hiểu việc sử dụng kmalloc cho các khu vực lớn ; nhưng đối với các phân bổ nhỏ, tại sao không sử dụng vmalloc để tránh phân mảnh bộ nhớ vật lý?
FreeMemory 22/09/08

Bởi vì bạn nên tin tưởng vào hạt nhân để làm những gì tốt nhất; nếu nó cho rằng phân bổ một đoạn duy nhất là tốt hơn, nó sẽ làm như vậy. vmalloc chỉ dành cho khi bạn hoàn toàn phải có một đoạn liền kề.
Dark Shikari 22/09/08

Tôi đoán điều đó có lý, nhưng nó có vẻ phản trực giác. kmalloc nghe có vẻ như nó phải được sử dụng khi hiệu suất là mối quan tâm hàng đầu (tức là tôi không thể bị cản trở bởi IO đĩa). Ngoài ra, GFP_ATOMIC thì sao?
FreeMemory

2

Trên hệ thống 32 bit, kmalloc () trả về địa chỉ logic hạt nhân (mặc dù là địa chỉ ảo) có ánh xạ trực tiếp (thực sự với độ lệch không đổi) đến địa chỉ vật lý. Ánh xạ trực tiếp này đảm bảo rằng chúng ta nhận được một phần RAM vật lý liền kề. Phù hợp với DMA trong đó chúng tôi chỉ cung cấp con trỏ ban đầu và mong đợi một ánh xạ vật lý liền kề sau đó cho hoạt động của chúng tôi.

vmalloc () trả về địa chỉ ảo hạt nhân mà có thể không có ánh xạ liền kề trên RAM vật lý. Hữu ích cho việc phân bổ bộ nhớ lớn và trong những trường hợp chúng ta không quan tâm đến việc bộ nhớ được phân bổ cho quá trình của chúng ta liên tục cũng trong RAM Vật lý.


1

Một trong những điểm khác biệt khác là kmalloc sẽ trả về địa chỉ logic (nếu bạn chỉ định GPF_HIGHMEM). Địa chỉ logic được đặt trong "bộ nhớ thấp" (trong gigabyte đầu tiên của bộ nhớ vật lý) và được ánh xạ trực tiếp đến địa chỉ vật lý (sử dụng macro __pa để chuyển đổi nó). Thuộc tính này ngụ ý bộ nhớ kmalloced là bộ nhớ liên tục.

Mặt khác, Vmalloc có thể trả về các địa chỉ ảo từ "bộ nhớ cao". Những địa chỉ này không thể được chuyển đổi thành địa chỉ vật lý theo kiểu trực tiếp (bạn phải sử dụng hàm Virt_to_page).

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.