2010-01-07 11 views
11

मैं मॉलॉक्स के उपयोग की निगरानी करना चाहता हूं और मॉलोक और फ्री हुक का उपयोग करके किसी एप्लिकेशन में मुक्त होना चाहता हूं।एक थ्रेड सुरक्षित तरीके से glibc malloc हुक का उपयोग कर

यहाँ प्रलेखन http://www.gnu.org/s/libc/manual/html_node/Hooks-for-Malloc.html

उदाहरण पृष्ठ से आप देख सकते हैं कि my_malloc_hook क्षणिक malloc बंद हुक (या श्रृंखला में पिछले हुक करने के लिए) से पहले फिर से लागू malloc स्विच करता है।

बहु-थ्रेडेड अनुप्रयोगों की निगरानी करते समय यह एक समस्या है (स्पष्टीकरण के लिए प्रश्न का अंत देखें)।

इंटरनेट पर मिली मॉलोक हुक के उपयोग के अन्य उदाहरण एक ही समस्या है।

क्या इस फ़ंक्शन को बहु-थ्रेडेड एप्लिकेशन में सही ढंग से काम करने के लिए फिर से लिखने का कोई तरीका है?

उदाहरण के लिए, क्या एक आंतरिक libc फ़ंक्शन है जो मॉलोक हुक आ सकता है जो मेरे हुक को निष्क्रिय करने की आवश्यकता के बिना आवंटन को पूरा करता है।

मैं कॉर्पोरेट कानूनी नीति के कारण libc स्रोत कोड को नहीं देख सकता, इसलिए उत्तर स्पष्ट हो सकता है।

मेरा डिज़ाइन स्पेक कहता है कि मैं मॉलोक को एक अलग मॉलोक डिज़ाइन से प्रतिस्थापित नहीं कर सकता।

मुझे लगता है कि कोई अन्य हुक खेलने में नहीं हैं।


अद्यतन

के बाद से malloc हुक अस्थाई रूप से malloc सर्विसिंग निकाल दिया जाता है, एक और धागा malloc कॉल कर सकते हैं और नहीं हुक मिलता है।

यह सुझाव दिया गया है कि मॉलोक के पास एक बड़ा ताला है जो इसे होने से रोकता है, लेकिन यह दस्तावेज नहीं है, और तथ्य यह है कि मैं प्रभावी रूप से मॉलोक को कॉल करता हूं, यह सुझाव देता है कि किसी भी लॉक को हुक के बाद मौजूद होना चाहिए, या जॉली चालाक होना चाहिए :

caller -> 
    malloc -> 
    malloc-hook (disables hook) -> 
     malloc -> # possible hazard starts here 
     malloc_internals 
     malloc <- 
    malloc-hook (enables hook) <- 
    malloc 
caller 
+0

यदि हम में से कोई भी libc स्रोत को देखता है और आपको इसके आधार पर जानकारी देता है, तो आप कानूनी रूप से उसी स्थिति में होंगे। –

+0

आप libc स्रोत कोड पर * क्यों नहीं देख सकते हैं? – Will

+0

क्योंकि मैं जीपीएल कोड के साथ हमारे मालिकाना कोड को प्रदूषित कर सकता हूं। बस यह कहा जा रहा है कि एक विशेष कार्य वह करेगा जो मुझे चाहिए वह समस्या नहीं है। –

उत्तर

8

UPDATED

आप right हैं __malloc_hooks पर भरोसा नहीं करने के लिए; मैंने कोड पर देखा है, और वे हैं - चौंकाने वाला पागलपन - धागा सुरक्षित नहीं है।

मॉलोक को बहाल करने और पुनः दर्ज करने के बजाए विरासत में हुकों को सीधे आमंत्रित करना, उस दस्तावेज़ से विचलित होना प्रतीत होता है जो आप आरामदायक सुझाव देने के लिए थोड़ा सा उद्धृत करते हैं।

http://manpages.sgvulcan.com/malloc_hook.3.php से:

हुक चर धागा सुरक्षित ताकि वे अब पदावनत कर रहे हैं नहीं कर रहे हैं। प्रोग्रामर को "malloc" और "free" जैसे कार्यों को परिभाषित और निर्यात करके प्रासंगिक कार्यों में कॉल को प्राथमिकता देना चाहिए।

डिबग malloc/realloc/मुक्त कार्यों सुई उचित तरीके से अपने खुद के पुस्तकालय है कि इन कार्यों के लिए अपने 'डिबग' संस्करणों का निर्यात करता है, और फिर असली लोगों को ही defers प्रदान करना है। सी लिंकिंग स्पष्ट क्रम में किया जाता है, इसलिए यदि दो पुस्तकालय एक ही कार्य की पेशकश करते हैं, तो पहले निर्दिष्ट का उपयोग किया जाता है। आप एलडी_PRELOAD तंत्र का उपयोग कर यूनिक्स पर लोड-टाइम पर अपने मॉलोक को इंजेक्ट भी कर सकते हैं।

http://linux.die.net/man/3/efence इलेक्ट्रिक बाड़ का वर्णन करता है, जो इन दोनों दृष्टिकोणों का विवरण देता है।

यदि आप आवश्यक हैं तो इन डीबग कार्यों में यदि आप अपने लॉकिंग का उपयोग कर सकते हैं।

+0

प्रश्न शायद है: क्या हुक को लॉक किया जाएगा या क्या यह malloc() के अंदर होता है? मुझे लगता है कि हुक बाहर होने के बिना हुक बेकार होगा लेकिन मुझे आश्चर्य है कि रिकर्सिव कॉलिंग कैसे काम करती है। –

+0

रिकर्सिव कॉलिंग रिकर्सिव लॉक के साथ काम कर सकती है - एक बार थ्रेड लॉक होने के बाद, इसे कई बार हासिल करने की अनुमति है। – Novelocrat

+0

अच्छा, यह सच हो सकता है, लेकिन जब तक मुझे पता न हो कि यह सच है, मैं इसका उपयोग नहीं कर सकता, क्योंकि यह टूट सकता है। इसके अलावा मैं यह नहीं बता सकता कि भविष्य में मॉलोक कार्यान्वयन बहु-थ्रेड प्रदर्शन को बढ़ाने के लिए अलग-अलग ताले वाले एकाधिक मॉलोक जोन की अनुमति दे सकता है या नहीं। –

2

malloc के लिए सभी कॉल() के बाद से अपने हुक के माध्यम से जाना होगा, तो आप एक सेमाफोर पर सिंक्रनाइज़ कर सकते हैं (जब तक प्रतीक्षा करें यह मुफ़्त है, यह ताला, हुक हथकंडा और सेमाफोर मुक्त)।

[संपादित करें] IANAL लेकिन ... आप उपयोग अपने कोड में glibc, तो आप कोड देख सकते हैं कर सकते हैं (क्योंकि यह LGPL है, यह का उपयोग कर किसी स्रोत की एक प्रति है करने के लिए अनुमति दी जानी चाहिए)। इसलिए मुझे यकीन नहीं है कि आप कानूनी स्थिति को सही ढंग से समझ चुके हैं या शायद आपको कानूनी रूप से आपकी कंपनी द्वारा ग्लिब का उपयोग करने की अनुमति नहीं है।

[EDIT2] कुछ सोचने के बाद, मुझे लगता है कि कॉल पथ का यह हिस्सा किसी प्रकार के लॉक द्वारा संरक्षित किया जाना चाहिए जो ग्लिब आपके लिए बनाता है। अन्यथा, बहु-थ्रेडेड कोड में हुक का उपयोग कभी भी भरोसेमंद काम नहीं करेगा और मुझे यकीन है कि दस्तावेज़ इसका उल्लेख करेंगे। चूंकि malloc() थ्रेड सुरक्षित होना चाहिए, इसलिए हुक भी होना चाहिए।

यदि आप अभी भी चिंतित हैं, तो मैं एक छोटे परीक्षण कार्यक्रम को दो धागे के साथ लिखने का सुझाव देता हूं जो एक लूप में आवंटित और मुक्त स्मृति प्रदान करते हैं। हुक में एक काउंटर बढ़ाएं। दस लाख राउंड के बाद, काउंटर बिल्कुल दो मिलियन होना चाहिए। यदि यह धारण करता है, तो हुक malloc() लॉक द्वारा भी सुरक्षित है।

[EDIT3] यदि परीक्षण विफल रहता है, तो, आपकी कानूनी स्थिति के कारण, मॉनिटर को कार्यान्वित करना संभव नहीं है। अपने मालिक को बताओ और उसे इसके बारे में फैसला करने दें।

[EDIT4] Googling एक बग रिपोर्ट से इस टिप्पणी कर दिया:

हुक थ्रेड-सुरक्षित नहीं हैं। अवधि। आप क्या ठीक करने की कोशिश कर रहे हैं?

यह मार्च 200 9 से libc/malloc/malloc.c में एक बग के बारे में एक चर्चा का हिस्सा है जिसमें एक फिक्स शामिल है। तो शायद के बाद glibc का एक संस्करण यह दिनांक काम करता है लेकिन गारंटी नहीं प्रतीत होती है। यह जीसीसी के आपके संस्करण पर निर्भर करता है।

+0

मुझे मेरी कंपनी द्वारा जीपीएल कोड देखने की अनुमति नहीं है। वे नियम हैं। –

+0

चूंकि हुक कोड को मॉलोक को दोबारा शुरू करने से पहले हुक कोड को हटाना चाहिए, एक दूसरा धागा जो मॉलोक को आमंत्रित करता है, जबकि मैंने अपने हुक को अनकही किया है, हुक का उपयोग नहीं करेगा। –

+0

@Alex मुझे अनुमान है कि इसका मतलब है कि आपको जीपीएल कोड देखने या उपयोग करने की अनुमति नहीं है? –

3

मुझे एक ही समस्या है। मैंने इसे उस उदाहरण के साथ हल किया है। अगर हम THREAD_SAFE को परिभाषित नहीं करते हैं, तो हमारे पास उस व्यक्ति द्वारा दिया गया उदाहरण है, और हमारे पास सेगमेंटेशन त्रुटि है। यदि हम THREAD_SAFE को परिभाषित करते हैं, तो हमारे पास कोई सेगमेंटेशन त्रुटि नहीं है।

#include <malloc.h> 
#include <pthread.h> 

#define THREAD_SAFE 
#undef THREAD_SAFE 

/** rqmalloc_hook_ */ 

static void* (*malloc_call)(size_t,const void*); 

static void* rqmalloc_hook_(size_t taille,const void* appel) 
{ 
void* memoire; 

__malloc_hook=malloc_call; 
memoire=malloc(taille);  
#ifndef THREAD_SAFE 
malloc_call=__malloc_hook; 
#endif 
__malloc_hook=rqmalloc_hook_; 
return memoire; 
} 

/** rqfree_hook_ */ 

static void (*free_call)(void*,const void*); 

static void rqfree_hook_(void* memoire,const void* appel) 
{ 
__free_hook=free_call; 
free(memoire);    
#ifndef THREAD_SAFE 
free_call=__free_hook;  
#endif 
__free_hook=rqfree_hook_; 
} 

/** rqrealloc_hook_ */ 

static void* (*realloc_call)(void*,size_t,const void*); 

static void* rqrealloc_hook_(void* memoire,size_t taille,const void* appel) 
{ 
__realloc_hook=realloc_call;  
memoire=realloc(memoire,taille); 
#ifndef THREAD_SAFE 
realloc_call=__realloc_hook;  
#endif 
__realloc_hook=rqrealloc_hook_; 
return memoire; 
} 

/** memory_init */ 

void memory_init(void) 
{ 
    malloc_call = __malloc_hook; 
    __malloc_hook = rqmalloc_hook_; 

    free_call = __free_hook; 
    __free_hook = rqfree_hook_; 

    realloc_call = __realloc_hook; 
    __realloc_hook = rqrealloc_hook_; 
} 

/** f1/f2 */ 

void* f1(void* param) 
{ 
void* m; 
while (1) {m=malloc(100); free(m);} 
} 

void* f2(void* param) 
{ 
void* m; 
while (1) {m=malloc(100); free(m);} 
} 

/** main */ 
int main(int argc, char *argv[]) 
{ 
memory_init(); 
pthread_t t1,t2; 

pthread_create(&t1,NULL,f1,NULL); 
pthread_create(&t1,NULL,f2,NULL); 
sleep(60); 
return(0); 
} 
0

मॉलोक में रिकर्स करते समय थ्रेड-सुरक्षित तरीके से मॉलोक हुक का उपयोग करने का कोई तरीका नहीं है। इंटरफेस बुरी तरह से डिजाइन किया गया है, शायद मरम्मत से परे।

भले ही आप अपने हुक कोड में एक म्यूटेक्स डालते हैं, समस्या यह है कि malloc में कॉल उन ताले को तब तक नहीं देखते जब तक कि वे हुक तंत्र से गुजरने के बाद, और हुक तंत्र से गुजरने के लिए, वे वैश्विक चर को देखते हैं (हुक पॉइंटर्स) आपके म्यूटेक्स को प्राप्त किए बिना। चूंकि आप एक थ्रेड में इन पॉइंटर्स को सहेज रहे हैं, बदल रहे हैं और बहाल कर रहे हैं, इसलिए अन्य थ्रेड में आवंटक कॉल उनसे प्रभावित होते हैं।

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

वैकल्पिक रूप से, ग्लिबैक एक आंतरिक मॉलोक इंटरफ़ेस प्रदान कर सकता है जो हुक का आह्वान नहीं करता है।

एक और शेन डिजाइन हुक के लिए थ्रेड-स्थानीय भंडारण का उपयोग होगा। एक हुक को ओवरराइड करना और बहाल करना एक धागे में किया जाएगा, बिना किसी धागे द्वारा देखे गए हुक को परेशान किए।

जैसा कि यह खड़ा है, आप ग्लिब मॉलोक हुक का सुरक्षित रूप से उपयोग करने के लिए क्या कर सकते हैं, मॉलोक में रिकर्सिंग से बचने के लिए है। हुक कॉलबैक के अंदर हुक पॉइंटर्स को न बदलें, और बस अपना खुद का आवंटक कॉल करें।

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