2012-01-02 26 views
7

Tôi cần kích thước lại bản sao của tệp mmap rất lớn trong khi vẫn cho phép truy cập đồng thời vào chuỗi trình đọc. Cách đơn giản là sử dụng hai ánh xạ MAP_SHARED (phát triển tệp, sau đó tạo ánh xạ thứ hai bao gồm vùng được phát triển) trong cùng một quá trình trên cùng một tệp và sau đó hủy ánh xạ ánh xạ cũ khi tất cả người đọc có thể truy cập vào nó xong rồi. Tuy nhiên, tôi tò mò nếu kế hoạch dưới đây có thể hoạt động, và nếu có thì có lợi thế nào không.Thay đổi kích thước nhanh của tệp mmap

  1. mmap một tập tin với MAP_PRIVATE
  2. làm chỉ đọc truy cập vào bộ nhớ này trong nhiều bài
  3. hoặc mua lại một mutex cho các tập tin, ghi vào bộ nhớ (giả định này được thực hiện theo một cách mà các độc giả, có thể đọc bộ nhớ đó, không bị rối loạn bởi nó)
  4. hoặc có được mutex, nhưng tăng kích thước của tệp và sử dụng mremap để di chuyển đến địa chỉ mới (thay đổi kích thước ánh xạ mà không cần sao chép hoặc tệp không cần thiết IO.)

Phần điên rồ xuất hiện tại (4). Nếu bạn di chuyển bộ nhớ, địa chỉ cũ trở nên không hợp lệ và người đọc vẫn đang đọc nó, có thể đột nhiên bị vi phạm quyền truy cập. Điều gì sẽ xảy ra nếu chúng ta sửa đổi các độc giả để bẫy vi phạm truy cập này và sau đó khởi động lại hoạt động (nghĩa là không đọc lại địa chỉ xấu, tính lại địa chỉ cho offset và địa chỉ cơ sở mới từ mremap). nhưng theo ý kiến ​​của tôi, người đọc chỉ có thể đọc dữ liệu ở địa chỉ cũ hoặc không thành công với vi phạm truy cập và thử lại. Nếu được chăm sóc đầy đủ, nên được an toàn. Kể từ khi tái định cỡ sẽ không xảy ra thường xuyên, người đọc cuối cùng sẽ thành công và không bị mắc kẹt trong một vòng lặp thử lại.

Sự cố có thể xảy ra nếu không gian địa chỉ cũ được sử dụng lại trong khi người đọc vẫn có con trỏ đến nó. Sau đó, sẽ không có vi phạm truy cập, nhưng dữ liệu sẽ không chính xác và chương trình đi vào vùng lân cận và kẹo đầy đất của hành vi không xác định (trong đó thường không có kỳ lân và kẹo.)

Nhưng nếu bạn kiểm soát phân bổ hoàn toàn và có thể chắc chắn rằng bất kỳ phân bổ nào xảy ra trong giai đoạn này không bao giờ tái sử dụng không gian địa chỉ cũ đó, thì đây không phải là vấn đề và hành vi không nên được xác định.

Tôi có đúng không? Có thể làm việc này? Có lợi thế nào cho việc này khi sử dụng hai ánh xạ MAP_SHARED không?

+0

Bạn chỉ có thể sử dụng khóa đọc/ghi và bảo vệ ánh xạ lại dưới khóa ghi, Không? – fge

+0

Tôi đoán rằng nút cổ chai là đĩa. Bạn có chắc là nó đáng giá không? sao chép các tệp lớn từ đĩa luôn mất thời gian, vì đĩa là thiết bị cơ học chậm. –

+0

fge, có nhưng khóa trên các chủ đề đọc là ra khỏi câu hỏi trong trường hợp này – Eloff

Trả lời

4

Thật khó để tôi tưởng tượng một trường hợp bạn không biết giới hạn trên về mức độ lớn của tệp. Giả sử đó là sự thật, bạn có thể "đặt trước" không gian địa chỉ cho kích thước tối đa của tệp bằng cách cung cấp kích thước đó khi tệp được ánh xạ đầu tiên bằng mmap(). Tất nhiên, bất kỳ truy cập nào vượt quá kích thước thực của tệp sẽ gây ra vi phạm truy cập, nhưng đó là cách bạn muốn nó hoạt động - bạn có thể tranh luận rằng việc đặt không gian địa chỉ bổ sung đảm bảo vi phạm quyền truy cập thay vì rời khỏi phạm vi địa chỉ đó mở để được sử dụng bởi các cuộc gọi khác tới những thứ như mmap() hoặc malloc().

Dù sao, vấn đề là giải pháp của tôi, bạn không bao giờ di chuyển phạm vi địa chỉ, bạn chỉ thay đổi kích thước và bây giờ khóa của bạn xung quanh cấu trúc dữ liệu cung cấp kích thước hợp lệ hiện tại cho mỗi chuỗi.

Giải pháp của tôi không hoạt động nếu bạn có quá nhiều tệp để ánh xạ tối đa cho mỗi tệp chạy không gian địa chỉ, nhưng đây là độ tuổi của không gian địa chỉ 64 bit để hy vọng kích thước bản đồ tối đa của bạn không vấn đề.

(Chỉ cần đảm bảo rằng tôi không quên điều gì đó ngu ngốc, tôi đã viết một chương trình nhỏ để thuyết phục bản thân mình tạo ánh xạ kích thước lớn hơn tệp cho phép vi phạm truy cập khi bạn cố gắng truy cập vượt quá kích thước tệp, và sau đó hoạt động tốt khi bạn ftruncate() tệp lớn hơn, tất cả cùng một địa chỉ được trả lại từ lệnh mmap() đầu tiên.)

+0

Đây là ý tưởng đầu tiên của tôi, nhưng không gian địa chỉ đáng buồn bị giới hạn ở 8TB trong các hệ điều hành hiện đại, có nghĩa là nếu có rất nhiều tập tin được ánh xạ bộ nhớ thì bạn có thể đặt không gian địa chỉ tối đa. Người ta có thể sử dụng mmap với MAP_NORESERVE để dự trữ nhiều không gian địa chỉ nhất có thể khi khởi động chương trình và sau đó phân bổ từ đó với MAP_FIXED, phân phối đồng đều lúc đầu và sau đó lấy từ bản đồ sử dụng ít nhất khi hết. Sau đó, sử dụng chiến lược ở trên hoặc memcpy tiêu chuẩn nếu một mmap hết dung lượng và không có không gian liền kề dành riêng. – Eloff

+0

nơi nào bạn nhận được con số 8TB của bạn từ đâu? – camelccc

+2

Linux có thể quản lý 64TB bộ nhớ ảo trong một không gian địa chỉ 128TB. Bạn không chắc chắn nếu bạn có nhiều tệp lớn hơn 128TB (ngay cả khối lượng RAID hoàn chỉnh trên chia sẻ mạng của tôi chỉ là 24TB, nhưng số dặm của bạn có thể thay đổi). Bạn không phải là Google, phải không? – Damon

Các vấn đề liên quan