2012-11-16 35 views
8

मैं आईओएस पर ऑडियो फ़ाइलों को पढ़ने और चलाने के लिए एमएमएपी का उपयोग करने की कोशिश कर रहा हूं। यह लगभग 400 एमबी तक फ़ाइलों के लिए ठीक काम करता है। लेकिन जब मैं 500 एमबी फ़ाइल आज़माता हूं, तो मुझे एक EohanM त्रुटि मिलती है।आईओएस पर एमएमएपी क्यों विफल रहता है?

char *path = [[[NSBundle mainBundle] pathForResource: @"test500MB" ofType: @"wav"] cStringUsingEncoding: [NSString defaultCStringEncoding]]; 
FILE *f = fopen(path, "rb"); 
fseek(f, 0, SEEK_END); 
int len = (int)ftell(f); 
fseek(f, 0, SEEK_SET); 

void *raw = mmap(0, len, PROT_READ, MAP_SHARED, fileno(f), 0); 

if (raw == MAP_FAILED) { 
    printf("MAP_FAILED. errno=%d", errno); // Here it says 12, which is ENOMEM. 
} 

क्यों?

मुझे "700 एमबी वर्चुअल मेमोरी सीमा" जैसे उत्तर से प्रसन्नता होगी, लेकिन कभी-कभी पता स्थान खंडित होता है, इसलिए आपको 700 एमबी मिलते हैं लेकिन छोटे हिस्सों में "। (यह सिर्फ अटकलें हैं, मैं अभी भी एक जवाब की जरूरत है)

आभासी स्मृति के बारे में एप्पल डॉक पेज का कहना है:

हालांकि ओएस एक्स एक समर्थन दुकान का समर्थन करता है, आईओएस नहीं करता है। आईफोन अनुप्रयोगों में, केवल पढ़ने योग्य डेटा जो डिस्क पर पहले से है (जैसे कोड पेज) को स्मृति से हटा दिया गया है और आवश्यकतानुसार डिस्क से पुनः लोड किया गया है।

जो यह पुष्टि करता है कि mmap को भौतिक स्मृति से बड़े ब्लॉक के लिए काम करना चाहिए, लेकिन अभी भी यह स्पष्ट नहीं करता है कि मैं इतनी कम सीमा क्यों मार रहा हूं।

अद्यतन

  • This answer दिलचस्प है, लेकिन 500MB अच्छी तरह से 700MB सीमा यह उल्लेख नीचे है।
  • This discussionसन्निहित स्मृति का उल्लेख है। तो स्मृति विखंडन एक असली मुद्दा हो सकता है?
  • मैं आइपॉड टच चौथी पीढ़ी का उपयोग कर रहा हूं जिसमें 256 एमबी भौतिक स्मृति है।
  • मेरे शोध का बिंदु यह देखने के लिए है कि से फ़ाइलों से केवल पढ़ने के डेटा को लोड करते समय मेमोरी को प्रबंधित करने का बेहतर तरीका है "जब तक आपको स्मृति चेतावनी नहीं मिलती तब तक आवंटित रखें"mmap इस हल करने के लिए एक अच्छा तरीका की तरह लग रहा था ...

अद्यतन 2

मैं mmap iOS के नए 64 बिट संस्करण के साथ पूरी तरह से काम करने की उम्मीद। एक बार जब मैं 64 बिट डिवाइस पर अपना हाथ लेता हूं तो परीक्षण करेगा।

+1

ठीक है, एक 500 एमबी फ़ाइल लगभग आईफोन 4 पर वास्तव में उपलब्ध मुफ्त रैम के रूप में लगभग दोगुनी है ... आप क्या उम्मीद करते हैं? 'mmap()' जादू नहीं है। –

+0

@ एच 2CO3 मैं उम्मीद करता हूं कि यह फ़ाइल डेटा में रैम में मांग करे, क्योंकि एमएमएड क्षेत्र का उपयोग किया जाता है। क्या यह mmap करता है? –

+0

यह एक कार्यान्वयन विस्तार है। जिस पर आपको भरोसा नहीं करना चाहिए, बी। जिसके बारे में आप उम्मीद नहीं करेंगे, सी। जिसे libSystem के स्रोत कोड के प्रासंगिक भागों को पढ़कर देखा जा सकता है। –

उत्तर

1

आगे की जांच पड़ताल करने के बाद और इस excellent blog post by John Carmack पढ़ने, यहाँ मेरी निष्कर्ष हैं:

  • 700MB iOS पर आभासी स्मृति के लिए सीमा होती है
  • यह कर सकते हैं या एक खंड में उपलब्ध नहीं हो सकता है; इस इसलिए पर डिवाइस स्थिति और एप्लिकेशन व्यवहार निर्भर करता है

, मज़बूती से फ़ाइल डेटा के 700MB लायक यह छोटे टुकड़ों में इसे तोड़ने के लिए आवश्यक है mmap करने के लिए।

+1

ठीक है। लिंक अब बेथेस्डा को रीडायरेक्ट करता है। – matrixugly

+2

@matrixugly शायद उम्र की जांच के कारण है। एक बार जब आप अपनी उम्र दर्ज कर लेंगे तो आप लिंक को फिर से लोड कर सकते हैं और यह काम करेगा। मैंने अभी जांच की है और ब्लॉग एंट्री अभी भी है। –

0

एनएसडीटा का उपयोग करें और यहां सीधे एमएमएपी स्पर्श न करें।

दोषयुक्त के फायदे प्राप्त करने के लिए पढ़ने, NSDataReadingMapped का उपयोग करें। NSData भी बाइट्स जब कम मेम स्थितियों

1

में मैं तुम्हारे लिए एक जवाब नहीं है को मुक्त कर देते है, लेकिन मैं 6.0.1 चल मेरे iPhone 5 पर अपने कोड का परीक्षण किया था और mmap एक 700MB आईएसओ फाइल पर सफल रहा। तो मैं अन्य कारकों से शुरू करूंगा और मान लें कि mmap ठीक से काम कर रहा है। शायद आप जो त्रुटि प्राप्त कर रहे हैं वह वास्तव में स्मृति के कारण नहीं है, या शायद डिवाइस पर स्मृति किसी भी तरह से थका हुआ है जहां mmap विफल हो रहा है; डिवाइस को रिबूट करने का प्रयास करें। आईओएस के आपके संस्करण के आधार पर, मुझे आश्चर्य है कि यदि संभवतः फ़ाइल के अंत में आपकी खोज पूरी तरह से फ़ाइल को आज़माने और मानचित्र करने के लिए एमएमएपी का कारण बन सकती है; आप इसे साफ़ करने का प्रयास कर सकते हैं और फ़ाइल आकार निर्धारित करने के लिए स्टेट का उपयोग कर सकते हैं, या फिर मैपिंग से पहले फ़ाइल डिस्क्रिप्टर को फिर से खोल सकते हैं। ये सब सिर्फ विचार हैं; अगर मैं आपकी त्रुटि को पुन: पेश कर सकता हूं, तो मुझे इसे ठीक करने में मदद करने में खुशी होगी।

+0

वास्तव में इसे आजमाने और अपने परिणामों की रिपोर्ट करने के लिए धन्यवाद। मुझे लगता है कि डिवाइस को पुनरारंभ करने में मदद मिल सकती है लेकिन यह कुछ भी है जो मैं अपने उपयोगकर्ताओं से ऐसा करने के लिए नहीं कह सकता हूं। –

+0

संभावित रूप से एमएमएपी को असफल होने की तलाश के लिए, मुझे नहीं लगता कि यह मामला है - मैंने समान परिणामों के बिना फ़ाइल आकार को हार्डकोड करने का प्रयास किया। –

0

आम तौर पर भौतिक मेमोरी की मात्रा के पास कुछ भी नहीं है कि आप फ़ाइल को एमएमएपी करने में सक्षम हैं या नहीं। यह सभी विवादास्पद स्मृति के बाद हम बात कर रहे हैं। आईओएस पर समस्या यह है कि, कम से कम आईओएस ऐप प्रोग्रामिंग गाइड के अनुसार, वर्चुअल मेमोरी मैनेजर केवल पढ़ने-योग्य वर्गों को ही बदल देता है ... सिद्धांत रूप में इसका मतलब यह होगा कि आप न केवल उपलब्ध पता स्थान की मात्रा से बाध्य हैं, लेकिन यदि आप PROT_READ के अलावा किसी अन्य चीज़ के साथ मैप कर रहे हैं, तो आप उपलब्ध रैम की मात्रा से भी बाध्य हैं। http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/TheiOSEnvironment/TheiOSEnvironment.html

फिर भी, यह हो सकता है कि आपके पास जो समस्या हो रही है वह वर्चुअल एड्रेस स्पेस में आपके मैपिंग के लिए काफी बड़ी मेमोरी की कमी है। जहां तक ​​मैं पा सकता हूं, ऐप्पल उपयोगकर्ता-मोड प्रक्रिया की ऊपरी मेमोरी सीमा प्रकाशित नहीं करता है। आमतौर पर पता स्थान का ऊपरी क्षेत्र कर्नेल के लिए आरक्षित है। उपयोगकर्ता मोड में काम करने के लिए आपके पास केवल 16-बिट मेमोरी हो सकती है।

डीबगर में मेमोरी मैप डंप किए बिना आप क्या नहीं देख सकते हैं, यह है कि प्रोसेस एड्रेस स्पेस में लोड की गई लाइब्रेरी (डाइलिब्स) साझा किए गए पुस्तकालयों (डिलिब) में कई (मैंने ऐप्पल से एक साधारण नमूना एप्लिकेशन में 100 से अधिक की गणना की है)। इनमें से प्रत्येक में भी mmap'd हैं, और प्रत्येक उपलब्ध पता स्थान खंडित करेगा।

जीडीबी में आप 'सूचना प्रो मैपिंग' के साथ मेमोरी मैपिंग को डंप करने में सक्षम होना चाहिए। दुर्भाग्यवश एलएलडीबी में एकमात्र समकक्ष जिसे मैं ढूंढने में सक्षम हूं, वह 'छवि सूची' है, जो केवल साझा लाइब्रेरी मैपिंग दिखाता है, न कि डेटा mmap mappings।

इस तरह से डीबगर का उपयोग करके आप यह निर्धारित करने में सक्षम होना चाहिए कि पता स्थान में उस डेटा के लिए पर्याप्त संगत ब्लॉक है जो आप मानचित्र करने का प्रयास कर रहे हैं, हालांकि यह ऊपरी सीमा को खोजने के लिए कुछ काम करता है (ऐप्पल को प्रकाशित करना चाहिए यह!)

+0

वास्तव में, ऐप्पल ने पहली बार आईओएस डिवाइस पर चल रहे ऐप के लिए ऊपरी मेमोरी सीमा प्रकाशित की है: यह तीसरी पीढ़ी के आईपैड पर 750 एमबी है। –

संबंधित मुद्दे