2010-08-19 14 views
13

Tôi đang cố gắng tìm hiểu cách remap các tệp ánh xạ bộ nhớ trên máy Mac (khi tôi muốn mở rộng không gian có sẵn).Có thực sự không có mremap ở Darwin?

Tôi thấy bạn bè trong thế giới Linux có mremap nhưng tôi không thể tìm thấy chức năng như vậy trong tiêu đề trên máy Mac của mình. /Developer/SDKs/MacOSX10.6.sdk/usr/include/sys/mman.h có sau đây:

  • mmap
  • mprotect
  • msync
  • munlock
  • munmap
  • nhưng không mremap

man mremap xác nhận nỗi sợ của tôi.

Tôi hiện đang phải munmapmmmap nếu tôi muốn thay đổi kích thước của tệp ánh xạ, liên quan đến việc vô hiệu hóa tất cả các trang được tải. Phải có cách tốt hơn. Chắc chắn?

Tôi đang cố viết mã sẽ hoạt động trên Mac OS X và Linux. Tôi có thể giải quyết cho một vĩ mô để sử dụng chức năng tốt nhất trong mỗi trường hợp nếu tôi nhưng tôi muốn làm điều đó đúng cách.

Trả lời

0

Bạn có thể ftruncate các tập tin với kích thước lớn (tạo ra một lỗ) và mmap tất cả của nó. Nếu tập tin là liên tục, tôi khuyên bạn nên điền vào các lỗ với các cuộc gọi viết chứ không phải bằng cách viết trong ánh xạ, nếu không các khối của tập tin có thể bị phân mảnh không cần thiết trên đĩa.

+0

Vì vậy, bạn đang đề xuất tôi nên phân bổ cho kích thước lớn nhất có thể mà tôi từng muốn và lấp đầy lỗ? Đó là một ý tưởng thú vị nhưng tôi lập bản đồ phạm vi địa chỉ tối đa có thể và không để lại thêm địa chỉ cho bất kỳ điều gì khác hoặc tôi sử dụng số tiền nhỏ hơn và có nguy cơ bị hết. Ngoài ra, điều này sẽ không được nền tảng (như được chỉ ra trong câu hỏi của tôi) như tôi không thể đảm bảo một số hệ thống tập tin sẽ không thực sự không phạm vi toàn bộ của tập tin và chất thải gigabyte. – Joe

+3

Bạn thậm chí không cần phải làm cho các tập tin trên đĩa lớn. Chỉ cần 'mmap' lớn hơn kích thước tệp. Việc truy cập vào cuối tập tin sẽ dẫn đến 'SIGBUS', vì vậy bạn cần' ftruncate' lâu hơn trước khi thử truy cập các phần mới thông qua 'mmap', nhưng nếu không thì nó sẽ ổn. –

0

Tôi không có kinh nghiệm về ánh xạ bộ nhớ, nhưng có vẻ như bạn có thể tạm thời ánh xạ cùng một tệp hai lần như một phương tiện để mở rộng ánh xạ mà không mất bất kỳ thứ gì.

int main() { 
    int fd; 
    char *fp, *fp2, *pen; 

     /* create 1K file */ 
    fd = open("mmap_data.txt", O_RDWR | O_CREAT, 0777); 
    lseek(fd, 1000, SEEK_SET); 
    write(fd, "a", 1); 

     /* map and populate it */ 
    fp = mmap(NULL, 1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
    pen = memset(fp, 'x', 1000); 

     /* expand to 8K and establish overlapping mapping */ 
    lseek(fd, 8000, SEEK_SET); 
    write(fd, "b", 1); 
    fp2 = mmap(NULL, 7000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 

     /* demonstrate that mappings alias */ 
    *fp = 'z'; 
    printf("%c ", *fp2); 

     /* eliminate first mapping */ 
    munmap(fp, 1000); 

     /* populate second mapping */ 
    pen = memset(fp2+10, 'y', 7000); 

     /* wrap up */ 
    munmap(fp2, 7000); 
    close(fd); 
    printf("%d\n", errno); 
} 

Đầu ra là zxxxxxxxxxyyyyyy.....

Tôi cho rằng, nếu bạn cân nhắc điều này, bạn có thể hết dung lượng địa chỉ nhanh hơn với mremap. Nhưng không có gì được đảm bảo bằng cách nào và nó có thể là mặt khác cũng an toàn.

+1

Đúng nếu tôi sai, nhưng điều này có gây ra nhiều IO hơn mmap MAP_PRIVATE và mremap không? Do MAP_SHARED flushing ghi vào đĩa? – Eloff

+0

@Eloff: Cách duy nhất là thử và xem. Bài đăng này rất cũ và tôi chưa bao giờ có nhiều động cơ để thực hiện thí nghiệm: vP. Nó sẽ là một chút ngạc nhiên khi nhìn thấy quá mức xả, vì tất cả bộ nhớ luôn được ánh xạ ít nhất một lần. Hệ điều hành chỉ nên xả khi ánh xạ cuối cùng bị loại bỏ, đúng không? – Potatoswatter

5

Nếu bạn cần thu nhỏ bản đồ, chỉ cần munmap phần cuối cùng bạn muốn xóa.

Nếu cần phóng to bản đồ, bạn có thể chênh lệch phù hợp với MAP_FIXED đến địa chỉ ngay phía trên bản đồ cũ, nhưng bạn cần phải cẩn thận. .

Văn bản ở trên bị tấn công là một ý tưởng khủng khiếp; MAP_FIXED về cơ bản là sai, trừ khi bạn đã biết những gì tại địa chỉ đích và muốn thay thế nó một cách nguyên tử. Nếu bạn đang cố tạo bản đồ cơ hội mới nếu phạm vi địa chỉ miễn phí, bạn cần sử dụng mmap với địa chỉ được yêu cầu nhưng mà không cầnMAP_FIXED và xem nó có thành công không và cung cấp cho bạn địa chỉ được yêu cầu; nếu nó thành công nhưng với một địa chỉ khác, bạn sẽ muốn hủy ánh xạ ánh xạ mới mà bạn vừa tạo và giả định rằng việc phân bổ tại địa chỉ được yêu cầu là không thể.

+0

Không thêm khu vực được ánh xạ thêm có nguy cơ không thể chỉ định tại địa chỉ đó không? – Joe

+0

Vâng, đó là những gì tôi đã cảnh báo. Nhưng tôi tin rằng 'MAP_FIXED' sẽ luôn luôn bản đồ trên đầu trang của một bản đồ hiện có (phá hủy bản đồ hiện có) thay vì thất bại, thậm chí còn tồi tệ hơn. –

1

Nếu bạn mở rộng khối lượng đủ lớn (nói, 64 MB, nhưng nó phụ thuộc vào tốc độ phát triển của nó) thì chi phí vô hiệu hóa bản đồ cũ là không đáng kể. Như mọi khi, điểm chuẩn trước khi giả định một vấn đề.