2009-04-15 13 views
23

Tôi có một số câu hỏi liên quan đến việc thực hiện mmap trong các hệ thống Linux mà dường như không có rất nhiều tài liệu:Linux mmap internals

Khi ánh xạ một tập tin vào bộ nhớ sử dụng mmap, làm thế nào bạn sẽ xử lý tìm nạp trước dữ liệu trong ví dụ tập tin?

I.e. điều gì sẽ xảy ra khi bạn đọc dữ liệu từ vùng được tạo hình? Dữ liệu đó có được chuyển đến bộ đệm L1/L2 không? Là nó đọc trực tiếp từ bộ nhớ cache đĩa? Các hướng dẫn ASM prefetchnta và tương tự có hoạt động trên mmap các vùng ed không?

Chi phí thực của cuộc gọi mmap thực tế là gì? Nó có liên quan đến lượng dữ liệu được ánh xạ hay không?

Hy vọng ai đó có một số thông tin chi tiết về điều này. Cảm ơn trước.

Trả lời

29

mmap về cơ bản là truy cập có lập trình vào hệ thống phụ Bộ nhớ ảo.

Khi bạn có, giả sử, tệp 1G và bạn mmap nó, bạn sẽ nhận được một con trỏ tới tệp "toàn bộ" giống như trong bộ nhớ.

Tuy nhiên, ở giai đoạn này, không có gì xảy ra để lưu hoạt động ánh xạ thực tế của việc đặt trước các trang cho tệp trong VM. (Tập tin lớn, hoạt động ánh xạ càng dài, tất nhiên.)

Để bắt đầu đọc dữ liệu từ tệp, bạn chỉ cần truy cập dữ liệu qua con trỏ bạn đã quay lại trong cuộc gọi mmap.

Nếu bạn muốn "tải trước" các phần của tệp, chỉ cần truy cập khu vực bạn muốn tải trước. Đảm bảo bạn truy cập TẤT CẢ các trang bạn muốn tải, vì VM sẽ chỉ tải các trang bạn truy cập. Ví dụ, nói trong tệp 1G của bạn, bạn có một vùng "chỉ mục" 10MB mà bạn muốn ánh xạ. Cách đơn giản nhất là chỉ "đi bộ chỉ mục của bạn" hoặc bất kỳ cấu trúc dữ liệu nào bạn có, cho phép trang VM trong dữ liệu khi cần thiết. Hoặc, nếu bạn "biết" rằng đó là "10MB đầu tiên" của tệp và kích thước trang của bạn cho máy ảo của bạn là 4K, thì bạn chỉ có thể truyền con trỏ mmap tới con trỏ char và chỉ lặp qua các trang.

void load_mmap(char *mmapPtr) { 
    // We'll load 10MB of data from mmap 
    int offset = 0; 
    for(int offset = 0; offset < 10 * 1024 * 1024; offset += 4 * 1024) { 
     char *p = mmapPtr + offset; 
     // deref pointer to force mmap load 
     char c = *p; 
    } 
} 

Vì bộ đệm L1 và L2, mmap không liên quan gì đến điều đó, đó là tất cả về cách bạn truy cập dữ liệu.

Vì bạn đang sử dụng hệ thống VM cơ bản, bất kỳ thứ gì xử lý dữ liệu trong khối mmap'd sẽ hoạt động (không bao giờ được lắp ráp).

Nếu bạn không thay đổi bất kỳ dữ liệu mmap'd, VM sẽ tự động tuôn ra các trang cũ như các trang mới là cần thiết Nếu bạn thực sự thay đổi chúng, sau đó VM sẽ viết những trang đó lại cho bạn.

+8

Sẽ không char "c = * p" được tối ưu hóa đi? Nên c được khai báo dễ bay hơi? –

+1

Trong các phiên bản gần đây của Linux, bạn có thể đặt MAP_POPULATE trong đối số cờ thành mmap() và các trang sẽ được kéo vào trước khi trả về cuộc gọi. Điều này sẽ chặn cuộc gọi trong một khoảng thời gian là một số chức năng của kích thước tệp, do đó, chạy hàm load_mmap() trong một chuỗi riêng biệt sẽ cải thiện hiệu suất nếu có công việc khác có thể được thực hiện song song trước khi nội dung tệp cần được đọc, đặc biệt là vì hầu hết công việc được thực hiện ở phía nhân. –

+0

Không 'mlock' tải trước các trang? –

3

Không có gì liên quan đến bộ đệm CPU; nó ánh xạ nó vào không gian địa chỉ ảo, và nếu nó được truy cập sau đó, hoặc khóa với mlock(), thì nó sẽ đưa nó vào bộ nhớ. Những gì CPU lưu trữ nó trong hoặc không có trong là không có gì bạn thực sự có quyền kiểm soát (ít nhất, không thông qua mmap).

Thường chạm vào các trang là cần thiết để làm cho nó được ánh xạ, nhưng nếu bạn làm một mlock hoặc mlockall, mà sẽ có tác dụng tương tự (chúng thường được đặc quyền).

Theo như chi phí liên quan, tôi không thực sự biết, bạn phải đo lường nó. Đoán của tôi là một mmap() mà không tải các trang trong nhiều hơn hoặc ít hơn một hoạt động liên tục thời gian, nhưng việc đưa các trang vào sẽ mất nhiều thời gian hơn với nhiều trang hơn.

các phiên bản gần đây của Linux cũng hỗ trợ một MAP_POPULATE cờ mà chỉ thị mmap để tải các trang trong ngay lập tức (có lẽ chỉ nếu có thể)

2

Trả lời câu hỏi ông Ravi Phulsundar của:

Nhiều quá trình có thể lập bản đồ cùng một tập tin miễn là các quyền được đặt chính xác. Nhìn vào trang mmap người đàn ông chỉ cần vượt qua MAP_SHARED cờ (nếu bạn cần để ánh xạ một tập tin sử dụng mmap2 thực sự lớn thay vì):

mmap

MAP_SHARED

Chia sẻ bản đồ này với tất cả các quá trình khác ánh xạ đối tượng này. Lưu trữ vào khu vực tương đương với ghi vào tệp. Tệp có thể không thực sự được cập nhật cho đến khi msync (2) hoặc munmap (2) được gọi.

0

bạn sử dụng MAP_SHARED