2010-12-16 9 views
21

मैं लगातार स्टॉक कोट्स (इंट्स, लांग, डबल्स इत्यादि) की एक फाइल में शामिल हूं। मेरे पास यह फ़ाइल mmap के साथ मेमोरी में मैप की गई है।मेमोरी-मैप किए गए फ़ाइल में शामिल

मेमोरी मैपिंग के हिस्से के रूप में नए जोड़े गए डेटा को उपलब्ध कराने का सबसे प्रभावी तरीका क्या है?

मैं समझता हूं कि मैं फ़ाइल को फिर से खोल सकता हूं (नई फ़ाइल डिस्क्रिप्टर) और उसके बाद नया डेटा प्राप्त करने के लिए इसे एमएमएपी करें लेकिन यह अक्षम है। एक और दृष्टिकोण जो मुझे सुझाया गया है, 1 एमबी भाग में फ़ाइल को पूर्व-आवंटित करना है, अंत तक पहुंचने तक एक विशिष्ट स्थिति में लिखें, फिर फ़ाइल को 1 एमबी पर ftruncate करें।

क्या अन्य दृष्टिकोण हैं?

डोस्ट बूस्ट इस के साथ मदद करते हैं?

उत्तर

17

बूस्ट। आईओएसट्रीम के पास निश्चित आकार केवल memory mapped files है, इसलिए यह आपकी विशिष्ट समस्या से मदद नहीं करेगा।

void *new_mapping = mremap(mapping, size, size + GROWTH, MREMAP_MAYMOVE); 
if (new_mapping == MAP_FAILED) 
    // handle error 
mapping = new_mapping; 

इस गैर पोर्टेबल है, लेकिन (और खराब प्रलेखित): लिनक्स एक अंतरफलक mremap जो इस प्रकार काम करता है। मैक ओएस एक्स में mremap नहीं है।

किसी भी मामले में, आप फ़ाइल को फिर से खोलने की जरूरत नहीं है बस इसे munmap और mmap इसे फिर से:

void *append(int fd, char const *data, size_t nbytes, void *map, size_t &len) 
{ 
    // TODO: check for errors here! 
    ssize_t written = write(fd, data, nbytes); 
    munmap(map, len); 
    len += written; 
    return mmap(NULL, len, PROT_READ, 0, fd, 0); 
} 

एक पूर्व आवंटन योजना यहाँ बहुत उपयोगी हो सकता है। फ़ाइल की वास्तविक लंबाई का ट्रैक रखना सुनिश्चित करें और बंद होने से पहले इसे एक बार फिर से छोटा करें।

2

man page for mremap पर देखना संभव होना चाहिए।

+1

mremap लिनक्स-विशिष्ट है, हालांकि। –

14

मुझे पता है कि उत्तर पहले से ही स्वीकार कर लिया गया है, लेकिन अगर मैं अपना उत्तर प्रदान करता हूं तो यह किसी और की मदद करेगा। समय से पहले एक बड़ी फाइल आवंटित करें, 10 जीबी आकार में कहें। समय से पहले इनमें से तीन फाइलें बनाएं, मैं उन्हें वॉल्यूम कहता हूं। अपने अंतिम ज्ञात स्थान को कहीं भी शीर्षलेख, दूसरी फ़ाइल इत्यादि जैसे ट्रैक रखें और फिर उस बिंदु से संलग्न रहें। यदि आप फ़ाइल के अधिकतम आकार तक पहुंचते हैं और अगली मात्रा में कमरे स्विच से बाहर निकलते हैं। यदि कोई और वॉल्यूम नहीं है, तो एक और वॉल्यूम बनाएं। ध्यान दें कि संभवतः आप यह सुनिश्चित करने के लिए कुछ वॉल्यूम करेंगे कि आपके एपेंड को नए वॉल्यूम के निर्माण की प्रतीक्षा न करें। इस तरह हम इसे कार्यान्वित करते हैं जहां मैं निगरानी के लिए एक डीवीआर प्रणाली में निरंतर आने वाले वीडियो/ऑडियो को संग्रहीत करने के लिए काम करता हूं। हम वीडियो क्लिप के लिए फ़ाइल नामों को स्टोर करने के लिए जगह बर्बाद नहीं करते हैं, यही कारण है कि हम वास्तविक फाइल सिस्टम का उपयोग नहीं करते हैं और इसके बजाय हम फ्लैट फ़ाइल जाते हैं और हम ऑफसेट्स, फ्रेम जानकारी (एफपीएस, फ्रेम प्रकार, चौड़ाई/ऊंचाई इत्यादि) को ट्रैक करते हैं।), समय रिकॉर्ड और कैमरा चैनल। आपके लिए स्टोरेज स्पेस आपके द्वारा किए जा रहे काम के लिए सस्ता है, जबकि आपका समय अमूल्य है। तो, जितना समय आप आगे बढ़ना चाहते हैं उतना पकड़ लें। आप मूल रूप से अपनी जरूरतों के लिए अनुकूलित अपनी खुद की फाइल सिस्टम को कार्यान्वित कर रहे हैं। सामान्य उपयोग फ़ाइल सिस्टम आपूर्ति की ज़रूरतें वही ज़रूरत नहीं हैं जिन्हें हमें अन्य क्षेत्रों में चाहिए।

0

मेरे 5 सेंट, लेकिन वे अधिक सी विशिष्ट हैं। सामान्य फ़ाइल बनाएं, लेकिन विशाल आकार को mmap करें - उदाहरण फ़ाइल 100K कहती है, लेकिन 1 जीबी या उससे अधिक mmap। फिर आप फ़ाइल आकार तक सबकुछ सुरक्षित रूप से एक्सेस कर सकते हैं। फ़ाइल आकार पर पहुंच के परिणामस्वरूप त्रुटि होगी। यदि आप 32 बिट ओएस पर हैं, तो बस mmap को बहुत बड़ा न करें, क्योंकि यह आपकी पता स्थान खाएगा।

0

आप खिड़कियों पर boost/iostreams/device/mapped_file.hpp उपयोग कर रहे हैं:

boost::filesystem::resize_file एक अपवाद फेंकता है तो एक पढ़ने मानचित्रण वस्तु साझा करने विशेषाधिकारों की कमी के कारण, खुला है। इसके बजाय, डिस्क पर फ़ाइल का आकार बदलने के लिए विंडोज-एपीआई का उपयोग करें, और पढ़ने mapped_file एस अभी भी खुला हो सकता है।

bool resize_file_wapi(string path, __int64 new_file_size) //boost::uintmax_t size 
{ 
    HANDLE handle = CreateFile(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 
    FILE_ATTRIBUTE_NORMAL, 0); 
    LARGE_INTEGER sz; 
    sz.QuadPart = new_file_size; 

    return handle != INVALID_HANDLE_VALUE 
    && ::SetFilePointerEx(handle, sz, 0, FILE_BEGIN) 
    && ::SetEndOfFile(handle) 
    && ::CloseHandle(handle); 
}