2013-07-09 28 views
8

In Linux, the mmap(2) man page giải thích rằng ánh xạ ẩn danhDấu mmap ẩn danh không được điền?

. . . không được hỗ trợ bởi bất kỳ tệp nào; nội dung của nó được khởi tạo bằng không.

The FreeBSD mmap(2) man page không đảm bảo tương tự về số không điền, mặc dù nó hứa hẹn rằng byte sau khi kết thúc tệp trong ánh xạ không ẩn danh không được lấp đầy.

Những hương vị nào của Unix hứa hẹn trả lại bộ nhớ không khởi tạo từ các bản đồ ẩn danh? Mà những người trở lại bộ nhớ zero-initialized trong thực tế, nhưng không hứa hẹn như vậy trên các trang người đàn ông của họ?

Đó là ấn tượng của tôi về việc không điền là một phần vì lý do bảo mật. Tôi tự hỏi có triển khai mmap nào không điền vào một trang đã được mmapped, munmapped, sau đó được mmapped một lần nữa, hoặc nếu bất kỳ triển khai điền vào một trang mới được ánh xạ với bit giả ngẫu nhiên hoặc một số khác không.

P.S. Apparently, even brk and sbrk used to guarantee zero-filled pages. thí nghiệm của tôi trên Linux dường như chỉ ra rằng, ngay cả khi trang đầy đủ là zero-điền khi lỗi trang sau khi một cuộc gọi sbrk phân bổ chúng, các trang một phần không:

#include <unistd.h> 
#include <stdio.h> 

int main() { 
    const intptr_t many = 100; 
    char * start = sbrk(0); 
    sbrk(many); 
    for (intptr_t i = 0; i < many; ++i) { 
    start[i] = 0xff; 
    } 
    printf("%d\n",(int)start[many/2]); 
    sbrk(many/-2); 
    sbrk(many/2); 
    printf("%d\n",(int)start[many/2]); 
    sbrk(-1 * many); 
    sbrk(many/2); 
    printf("%d\n",(int)start[0]); 
} 

Trả lời

7

Thật khó để nói cái nào hứa những gì mà không đơn giản toàn bộ liệt kê tất cả các trang của người đàn ông hoặc tài liệu phát hành khác, nhưng mã cơ bản xử lý MAP_ANON là (thường là luôn luôn?) cũng được sử dụng để ánh xạ trong không gian bss cho các tệp thực thi và không gian bss cần phải được lấp đầy. Vì vậy, nó khá darn khả năng. Đối với "cho bạn trở lại giá trị cũ của bạn" (hoặc một số giá trị khác không, nhưng có thể là giá trị cũ nhất của bạn) nếu bạn unmap và tái bản đồ, nó chắc chắn có thể, nếu một số hệ thống được "lười biếng "về deallocation. Tôi đã chỉ sử dụng một vài hệ thống hỗ trợ mmap ở vị trí đầu tiên (các dẫn xuất BSD và Linux) và không ai là lười biếng theo cách đó, ít nhất, không phải trong mã hạt nhân xử lý mmap.

Lý do sbrk có thể hoặc không thể điền vào một trang "được ghi lại" có thể gắn liền với lịch sử hoặc thiếu trang đó. Mã FreeBSD hiện tại khớp với những gì tôi nhớ từ cũ, trước mmap ngày: có hai biến bán bí mật, minbrkcurbrk và cả hai brksbrk sẽ chỉ gọi SYS_break (cuộc gọi hệ thống thực) nếu chúng đang di chuyển curbrk với một giá trị ít nhất là minbrk. (Trên thực tế, điều này có vẻ hơi bị hỏng: brk có hành vi ở-nhất nhưng sbrk chỉ bổ sung thêm đối số của nó để curbrk và gọi SYS_break vẻ vô hại kể từ khi kiểm tra hạt nhân, trong sys_obreak() trong /sys/vm/vm_unix.c, do đó, một quá âm sbrk() sẽ thất bại với EINVAL..)

Tôi phải xem thư viện Linux C (và sau đó có lẽ là mã hạt nhân) nhưng nó có thể đơn giản bỏ qua các nỗ lực để "giảm ngắt", và chỉ ghi lại giá trị "break logic" trong libc. Nếu bạn có mmap() và không có yêu cầu tương thích ngược, bạn có thể triển khai brk()sbrk() hoàn toàn bằng libc, sử dụng ánh xạ ẩn danh và sẽ không quan trọng để triển khai cả hai cách là "chỉ phát triển".