2012-08-25 19 views
5

मैं उदाहरण के लिए संकलन समय पर मेरी सी कार्यक्रम में सभी चर घोषित करने के लिए, चाहते हैं:अधिकतम आकार डेटा

char cache[CACHE_SIZE]; 
char udp_ring[MAX_UDP_PACKET_SIZE*MAX_REQUESTS]; 
int num_packets; 
char error_codes[NUM_ERRORS][MAX_ERROR_STRING]= { 
    {"Unknown user\n"}, 
    {"Wrong password\n"}, 
    .... 
}; 

सवाल है, वहाँ में चर के आकार पर किसी भी सीमा नहीं है एक सी प्रोग्राम जब वे बीएसएस या डेटा सेगमेंट में जाते हैं? उदाहरण के लिए यदि मैं 8 जीबी रैम का CACHE_SIZE घोषित करता हूं, तो यह काम करेगा? क्या 32 बिट्स या 64 बिट्स के लिए कोई अंतर है? मैं लिनक्स पर प्रोग्राम चलाने की योजना बना रहा हूं और मेरे RLIMIT_DATA कॉन्फ़िगरेशन में कोई प्रतिबंध नहीं होगा।

+0

"मैं संकलन समय पर अपने सी प्रोग्राम में सभी चर घोषित करना चाहता हूं" - तो रनटाइम पर उन्हें घोषित करने का एक तरीका है? –

+0

हाँ, लेकिन मैं glibc से लिंक नहीं करना चाहता, इसलिए मुझे malloc() – Nulik

+2

** sigh ** से बचने की आवश्यकता है - एक चर घोषित करना ऐसा नहीं है जो आपको लगता है। आप रनटाइम पर एक चर घोषित नहीं कर सकते हैं। एक सी किताब पकड़ो जाओ। –

उत्तर

3

आप जितना वर्चुअल मेमोरी प्रबंधित कर पाएंगे क्योंकि आपका कर्नेल प्रक्रियाओं को संभालने की अनुमति देता है: यह आर्किटेक्चर पर निर्भर करेगा।

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

यदि आप अपने सभी बफर को स्थिर रूप से आवंटित नहीं करते हैं और कर्नेल इसे फिट नहीं कर सकता प्रक्रिया वर्चुअल एड्रेस स्पेस में, इसे स्टार्ट-अप पर मारा जाएगा: 8 जीबी बफर का उपयोग करने से ज्यादातर 32-बिट आर्किटेक्चर पर इस व्यवहार का परिणाम होगा।

आप glibc के स्मृति प्रबंधन समारोह (malloc, ...), आप अपने खुद के स्मृति प्रबंधन पुस्तकालय रोल और एक LD_PRELOAD चाल के साथ इसका इस्तेमाल करने की अपनी प्रक्रिया के लिए मजबूर कर सकता है पर भरोसा नहीं करना चाहते हैं, तो इस तरह आप निर्धारित कर सकते हैं एक malloc/calloc/realloc/free (sbrk() का उपयोग करके) कार्यान्वयन अपनी आवश्यकताओं से मेल खाता है।

+0

ठीक है, जैसा कि मैंने समझा है कि 64 बिट मोड में स्थिर आवंटित चर के लिए कोई सीमा नहीं है, इसे इंटिलाइज्ड (बीएसएस) या प्रारंभिक (डेटा) नहीं किया जाएगा, सही? – Nulik

+1

वहां * 64-बिट्स आर्किटेक्चर पर वर्चुअल सीमा है, जो कर्नेल को संबोधित करने के लिए आरक्षित कुछ स्थान वर्चुअल एड्रेस स्पेस के 2^64 बाइट्स (16 एक्साबाइट) होगा। हालांकि, x86-64 (एएमडी और इंटेल) के वर्तमान कार्यान्वयन 48 बिट्स एड्रेस बिट्स (~ 256 टीबी वर्चुअल एड्रेस स्पेस) तक सीमित हैं, लेकिन मुझे पूरा यकीन है कि आप इस सीमा तक पहुंचने से पहले भौतिक रैम से बाहर चले जाएंगे। आईआईआरसी लिनक्स x86-64 पर प्रति प्रक्रिया 128TB वर्चुअल एड्रेस स्पेस की अनुमति देता है। – strnk

2

यदि आप glibc से लिंक नहीं करना चाहते हैं, तो आपको syscalls (syscalls(2) मैन पेज में सूचीबद्ध) करने में सक्षम होने के कुछ अजीब तरीकों को ढूंढना चाहिए। किसी भी एप्लिकेशन को कुछ सिस्को करना पड़ता है (उदा। open(2), read(2), write(2) ...)। ग्लिब का प्रयोग सिस्कोल को सी इंटरफ़ेस प्रदान करने के लिए भी किया जाता है। assembly howto बताता है कि बिना किसी असेंबली कोड (उदाहरण के लिए सी asm निर्देशों) के माध्यम से सीधे libc के बिना syscalls को कॉल करें। अप्रचलित _syscall(2) मैन पेज भी देखें। VDSO के लिए भी देखें।

आप mmap(2) और munmap(2) सिस्कोल का उपयोग करके अपना पता स्थान बदल सकते हैं। स्मृति आवंटित करने और जारी करने के लिए यह प्राथमिक संचालन है। Glibc उन्हें malloc और free लागू करने के लिए उपयोग करता है।

वैश्विक या स्थैतिक के रूप में सभी चर घोषित करना, इसे आरंभ करना (.data सेगमेंट) या साफ़ (.bss सेगमेंट) का एक महत्वपूर्ण नुकसान है: आप गतिशील रूप से स्मृति संसाधनों का उपयोग नहीं कर सकते हैं। और बहुत से प्रारंभिक डेटा होने के कारण एक महत्वपूर्ण लागत है: आपका ईएलएफ निष्पादन योग्य होगा।

लेकिन आपको वास्तव में समझाया जाना चाहिए कि आप ग्लिब से क्यों बचना चाहते हैं। सी में कोडिंग करते समय इसे टालना मुश्किल है। आप हल्के विकल्प जैसे dietlibc का उपयोग कर सकते हैं।

+0

धन्यवाद, बहुत उपयोगी जानकारी। मैं glibc से बचना चाहता हूं क्योंकि मैं कार्यक्रम को बाइनरी रूप में वितरित कर दूंगा, और मैं अलग-अलग लिनक्स वितरण के साथ असंगतता मुद्दों को नहीं लेना चाहता हूं। असल में मैं गतिशील आवंटन का उपयोग करूँगा, लेकिन यह केवल अपने हीप प्रबंधन दिनचर्या के साथ कैश के लिए होगा, मैं बस अन्य चर के लिए सीमा जानना चाहता था। – Nulik

+0

आप ग्लिबैक को स्थिर रूप से जोड़ने पर विचार कर सकते हैं, लेकिन यह आमतौर पर एक बुरा विचार है। आपको समझाया जाना चाहिए कि आप किस प्रकार का प्रोग्राम कोडिंग कर रहे हैं। क्या आपने इसे एक मुफ्त सॉफ्टवेयर (जैसे जीपीएल लाइसेंस प्राप्त) बनाने पर विचार किया? और यहां तक ​​कि आपके ग्लिबैक को स्थिर रूप से जोड़ना भी सभी असंगतताओं से बच नहीं पाएगा; ग्लिब का कुछ कर्नेल संस्करण से थोड़ा निर्भर करता है ... –

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