2012-05-07 13 views
10

अस्वीकरण: प्रश्न के लेखक Erlang औसत ज्ञान और सी का बुनियादी ज्ञानसी और Erlang: Erlang पोर्ट उदाहरण

मैं अब Interoperability Tutorial User Guide पढ़ रहा हूँ है। मैंने complex.c उदाहरण सफलतापूर्वक संकलित किया है और यह बिना किसी समस्या के एरलांग पोर्ट के साथ काम करता है।

हालांकि, मैं समझना चाहता हूं कि वास्तविक सी कोड कैसे काम करता है। मैं इसे सामान्य रूप से समझता हूं: उदाहरण में यह मानक इनपुट से 2 बाइट पढ़ता है और पहले बाइट को चेक करता है। पहले बाइट के आधार पर यह foo या bar फ़ंक्शन पर कॉल करता है। यह अभी मेरी समझ की सीमा है।

तो, हम ले अगर दोनों erl_comm.c:

/* erl_comm.c */ 

typedef unsigned char byte; 

read_cmd(byte *buf) 
{ 
    int len; 

    if (read_exact(buf, 2) != 2) 
    return(-1); 
    len = (buf[0] << 8) | buf[1]; 
    return read_exact(buf, len); 
} 

write_cmd(byte *buf, int len) 
{ 
    byte li; 

    li = (len >> 8) & 0xff; 
    write_exact(&li, 1); 

    li = len & 0xff; 
    write_exact(&li, 1); 

    return write_exact(buf, len); 
} 

read_exact(byte *buf, int len) 
{ 
    int i, got=0; 

    do { 
    if ((i = read(0, buf+got, len-got)) <= 0) 
     return(i); 
    got += i; 
    } while (got<len); 

    return(len); 
} 

write_exact(byte *buf, int len) 
{ 
    int i, wrote = 0; 

    do { 
    if ((i = write(1, buf+wrote, len-wrote)) <= 0) 
     return (i); 
    wrote += i; 
    } while (wrote<len); 

    return (len); 
} 

और port.c:

/* port.c */ 

typedef unsigned char byte; 

int main() { 
    int fn, arg, res; 
    byte buf[100]; 

    while (read_cmd(buf) > 0) { 
    fn = buf[0]; 
    arg = buf[1]; 

    if (fn == 1) { 
     res = foo(arg); 
    } else if (fn == 2) { 
     res = bar(arg); 
    } 

    buf[0] = res; 
    write_cmd(buf, 1); 
    } 
} 

क्या प्रत्येक कार्य वास्तव में वहाँ क्या करता है? li, len, i, wrote, got चर क्या वास्तव में सेवा करते हैं?

कुछ और छोटे सवाल:

  1. क्यों कार्यों किसी भी वापसी प्रकार की जरूरत नहीं है, यहां तक ​​कि void रों?
  2. जब एरलांग पोर्ट सी को डेटा भेजता है, तो पहला बाइट एक फ़ंक्शन कहलाता है। यदि बाइट दशमलव 1 रखता है, तो foo() कहा जाता है, यदि बाइट दशमलव 2 रखता है, तो bar() कहा जाता है। यदि किसी भी तरह से परिवर्तित नहीं किया गया है तो इस प्रोटोकॉल का उपयोग केवल 25 पैरामीटर के साथ 255 अलग-अलग सी कार्यों को कॉल करने के लिए किया जा सकता है। क्या वह सही है?
  3. "लम्बा संकेतक जोड़ना एरलांग बंदरगाह द्वारा स्वचालित रूप से किया जाएगा, लेकिन बाहरी सी प्रोग्राम में स्पष्ट रूप से किया जाना चाहिए"। इसका क्या मतलब है? कोड की किस पंक्ति पर यह किया जाता है?
  4. ट्यूटोरियल से: "डिफ़ॉल्ट रूप से, सी प्रोग्राम मानक इनपुट (फ़ाइल डिस्क्रिप्टर 0) से पढ़ना चाहिए और मानक आउटपुट (फ़ाइल डिस्क्रिप्टर 1) को लिखना चाहिए।" फिर: "ध्यान दें कि stdin और stdout buffered इनपुट/आउटपुट के लिए हैं और Erlang के साथ संचार के लिए उपयोग नहीं किया जाना चाहिए!" यहां कैच क्या है?
  5. क्यों buf[100] पर शुरू किया गया है?

उत्तर

8

इस उत्तर वैसे ही अस्वीकार है

आपका प्रारंभिक मॉडल एक सा नहीं है (मैं कर रहा हूँ नहीं एक Erlang या सी प्रोग्रामर, मैं सिर्फ एक ही सामग्री के माध्यम से जा रहा होता है)। जिस तरह से कोड वास्तव में काम करता है वह stdin से पहले दो बाइट्स को पढ़कर, यह मानते हुए कि यह वास्तविक संदेश की लंबाई को दर्शाता है, फिर stdin से कई बाइट पढ़ता है। इस विशिष्ट मामले में, ऐसा होता है कि वास्तविक संदेश हमेशा दो बाइट्स (एक फ़ंक्शन से संबंधित एक संख्या और इसे पास करने के लिए एक पूर्णांक तर्क) होता है।

0 - क)read_exactlen बाइट्स stdin से, पढ़ता read_cmdread_exact पहले का उपयोग करता है निर्धारित करने के लिए यह कितने बाइट्स पढ़ना चाहिए (या तो एक नंबर पहले दो बाइट्स द्वारा संकेतित, या कोई भी अगर वहाँ दो से कम उपलब्ध बाइट्स हैं), और फिर कई बाइट पढ़ने के लिए। write_exact लिखते हैं len बाइट्स stdout, write_cmd दो बाइट लंबाई शीर्षलेख आउटपुट के लिए write_exact का उपयोग करता है, उसके बाद उपयुक्त लंबाई के एक संदेश (उम्मीद है) के बाद।

0 - बी) मुझे लगता है कि len पर्याप्त रूप से ऊपर कवर किया गया है। li लेखन फ़ंक्शन के लिए दो-बाइट हेडर उत्पन्न करने के लिए उपयोग किए जाने वाले चर का नाम है (मैं आपको चरण-दर-चरण शिफ्ट ऑपरेशंस के माध्यम से चरणबद्ध नहीं ले सकता, लेकिन अंतिम परिणाम यह है कि len को भेजे गए पहले दो बाइट्स में दर्शाया गया है)। i एक मध्यवर्ती चर है जिसका मुख्य उद्देश्य यह सुनिश्चित करना प्रतीत होता है कि write और read कोई त्रुटि नहीं लौटाएं (यदि वे करते हैं, तो त्रुटि कोड read_exact/write_exact के परिणामस्वरूप लौटाया जाता है)। wrote और got ट्रैक रखें कि कितने बाइट्स लिखे/पढ़े गए हैं, इसमें len से अधिक होने से पहले युक्त लूप बाहर निकलते हैं।

1 - मुझे वास्तव में यकीन नहीं है। जिन संस्करणों के साथ मैं काम कर रहा था वे int टाइप हैं, लेकिन अन्यथा समान हैं। मुझे आपके द्वारा लिंक की गई मार्गदर्शिका के बजाय Programming Erlang के अध्याय 12 में से मेरा पता चला।

2 - यह सही है, लेकिन बंदरगाह प्रोटोकॉल का मुद्दा यह है कि आप अलग अलग तर्क भेजने के लिए इसे बदल सकते हैं (आप मनमाना तर्क भेज रहे हैं जो है, यह शायद एक बेहतर विचार सिर्फ उपयोग करने के लिए किया जाएगा बंदरगाहों के बजाय C Node विधि)। एक उदाहरण के रूप में, मैं हाल ही के टुकड़े में modified it subtly ताकि यह एक स्ट्रिंग भेजता है, क्योंकि मेरे पास केवल एक फ़ंक्शन है जिसे मैं सी पक्ष पर कॉल करना चाहता हूं, जिससे फ़ंक्शन निर्दिष्ट करने की आवश्यकता समाप्त हो जाती है। मुझे यह भी जिक्र करना चाहिए कि यदि आपके पास ऐसी प्रणाली है जिसे सी में लिखे गए 255 से अधिक विभिन्न परिचालनों को कॉल करने की आवश्यकता है, तो आप इसकी संरचना पर पुनर्विचार करना चाहेंगे (या केवल पूरे नौ पर जाएं और इसे सी में लिखें)।

3 - यह write_cmd समारोह में किया जाता है

read_cmd(byte *buf) 
{ 
    int len; 

    if (read_exact(buf, 2) != 2) // HERE 
    return(-1);     // HERE 
    len = (buf[0] << 8) | buf[1]; // HERE 
    return read_exact(buf, len); 
} 
read_cmd समारोह में

और

write_cmd(byte *buf, int len) 
{ 
    byte li; 

    li = (len >> 8) & 0xff;  // HERE 
    write_exact(&li, 1);   // HERE 

    li = len & 0xff;    // HERE 
    write_exact(&li, 1);   // HERE 

    return write_exact(buf, len); 
} 

। मुझे लगता है कि स्पष्टीकरण 0 - a) में शामिल है; यह एक हेडर है जो बताता है/पता लगाता है कि शेष संदेश कितना समय होगा (हाँ, इसका मतलब है कि यह केवल एक सीमित लंबाई हो सकता है, और वह लंबाई दो बाइट्स में व्यक्त की जानी चाहिए)।

4 - मुझे पूरा यकीन नहीं है कि यह यहां कैच क्यों होगा। विस्तृत करने के लिए परवाह?

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

+0

'buf' के बारे में आपकी धारणा सही है। यह एक सरणी है, यानी, एक निर्दिष्ट स्मृति क्षेत्र निर्दिष्ट निर्दिष्ट प्रकार के तत्वों को पकड़ने में सक्षम है। इस परिदृश्य में ढेर पर आवंटित स्मृति। स्मृति आवंटित करने का एक अलग तरीका 'पॉफ' को पॉइंटर बनाना होगा और इसे 'मॉलोक' का उपयोग करके ढेर पर आवंटित करना होगा (लेकिन फिर आपको यह सुनिश्चित करना होगा कि जब आप इसके साथ काम करेंगे तो स्मृति को मुक्त करें)। –

+0

के बारे में 4. पहले ट्यूटोरियल का कहना है कि सी प्रोग्राम stdin (फ़ाइल descriptor 0) से पढ़ना चाहिए और stdout (फ़ाइल descriptor 1) को लिखना चाहिए। फिर ट्यूटोरियल का कहना है कि एरडैंग के साथ संचार के लिए stdin/stdout का उपयोग नहीं किया जाना चाहिए। "क्या यह प्रत्यक्ष विरोधाभास नहीं है? वे एक उदाहरण सी प्रोग्राम प्रदान करते हैं जो stdin/stdout का उपयोग करता है और फिर वे कहते हैं कि इसका उपयोग नहीं किया जाना चाहिए, क्योंकि stdin/stdout buffered है। मुझे लगता है कि मुझे कुछ याद आती है। – skanatek

+1

@ मार्टिनली - ओह, सच है, मुझे लगता है। मैंने इसका मतलब यह लिया कि आपको इन बंदरगाहों का उपयोग एरलांग और सी प्रक्रियाओं के बीच आगे और आगे संचार करने के लिए नहीं करना चाहिए (यही कारण है कि सी नोड चीज के लिए है)। हम हालांकि नहीं हैं; एरलांग एक अनुरोध भेज रहा है और कार्यक्रम के प्रति आमंत्रण की एक 'इंट' प्रतिक्रिया की उम्मीद कर रहा है। मुझे लगता है कि मुझे गलत समझा या गलत तरीके से पढ़ा जा सकता है। – Inaimathi