2013-03-04 13 views
5

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

int main() 
{ 
    int pid; 
    FILE *fp; 
    fp = fopen("test.txt","w"); 
    char *buff; 
    int fd[2]; 
    int count = 0 ; 
    pipe(fd); 
    pid = fork(); 
    if(pid == 0) 
    { 
     close(fd[1]); 
     ioctl(fd[0], FIONREAD, &count); 
     fprintf(fp,"Value of count: %d ",count); 
     buff = malloc(count); 
     fprintf(fp,"\n TIME before read: %s",__TIME__); 
     read(fd[0], buff, count); 
     fprintf(fp,"\nbuffer: %s\n TIME after read %s", buff, __TIME__); 
    } 
    else{ 
     close(fd[0]); 
     sleep(10); //delay caused by application specific code replaced with sleep 
     write(fd[1],"THIS is it",10); 
    } 
    fclose(fp); 
    return 0; 
} 

कैसे बच्चे प्रक्रिया प्रतीक्षा करने के लिए?

उत्तर

5

आपका पाइप मोड को रोकने में खोला जाता है, और आप कुछ नहीं कर बदलने के लिए के बाद वह, जो संभवतः आपके इरादे से है।

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

चयन-लूप समेत ऐसा करने के कई तरीके हैं। यदि आप डेटा को उपलब्ध होने तक ब्लॉक को पढ़ते हैं, तो एक बाइट पर ऐसा करें और बाद में शेष डेटा भरें।

यह सही करने का कोई उदाहरण नहीं है, लेकिन यह एक छोटा सा नमूना है कि आप एक बाइट पर कैसे इंतजार कर सकते हैं, बाकी के लिए पाइप के पढ़ने के आकार का अनुरोध करें डेटा, इसे पढ़ें, और तब तक जारी रखें जब तक कि पाइप में कोई डेटा शेष न हो और माता-पिता अपना अंत बंद कर दें:

मुझे आशा है कि आपको यह उपयोगी लगेगा।

#include <stdio.h> 
#include <unistd.h> 
#include <sys/ioctl.h> 

int main() 
{ 
    int pid = 0; 

    // create pipe pair 
    int fd[2]; 
    pipe(fd); 

    pid = fork(); 
    if (pid == 0) 
    { 
     // child side 
     char *buff = NULL; 
     char byte = 0; 
     int count = 0; 

     // close write side. don't need it. 
     close(fd[1]); 

     // read at least one byte from the pipe. 
     while (read(fd[0], &byte, 1) == 1) 
     { 
      if (ioctl(fd[0], FIONREAD, &count) != -1) 
      { 
       fprintf(stdout,"Child: count = %d\n",count); 

       // allocate space for the byte we just read + the rest 
       // of whatever is on the pipe. 
       buff = malloc(count+1); 
       buff[0] = byte; 
       if (read(fd[0], buff+1, count) == count) 
        fprintf(stdout,"Child: received \"%s\"\n", buff); 
       free(buff); 
      } 
      else 
      { // could not read in-size 
       perror("Failed to read input size."); 
      } 
     } 

     // close our side 
     close(fd[0]); 
     fprintf(stdout,"Child: Shutting down.\n"); 
    } 
    else 
    { // close read size. don't need it. 
     const char msg1[] = "Message From Parent"; 
     const char msg2[] = "Another Message From Parent"; 
     close(fd[0]); 
     sleep(5); // simulate process wait 
     fprintf(stdout, "Parent: sending \"%s\"\n", msg1); 
     write(fd[1], msg1, sizeof(msg1)); 
     sleep(5); // simulate process wait 
     fprintf(stdout, "Parent: sending \"%s\"\n", msg2); 
     write(fd[1], msg2, sizeof(msg2)); 
     close(fd[1]); 
     fprintf(stdout,"Parent: Shutting down.\n"); 
    } 
    return 0; 
} 

आउटपुट

Parent: sending "Message From Parent" 
Child: count = 19 
Child: received "Message From Parent" 
Parent: sending "Another Message From Parent" 
Parent: Shutting down. 
Child: count = 27 
Child: received "Another Message From Parent" 
Child: Shutting down. 
1

समस्या पाइप को लिखे गए बाइट्स की संख्या प्राप्त करने के साथ है। आप इसे कांटा() के ठीक बाद प्राप्त कर रहे हैं। यदि पढ़ने की प्रक्रिया पहले निष्पादित होती है, तो इसमें कोई डेटा नहीं होगा (और गणना शून्य होगी)। यदि लेखन प्रक्रिया पहले निष्पादित होती है, तो इसमें कुछ डेटा होगा।

बच्चे की प्रक्रिया को दूसरी छोर पर डेटा लिखने तक कैसे प्रतीक्षा करें?

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


यहाँ अपने संशोधित उदाहरण है कि एक पूर्ण संदेश के लिए इंतजार कर रहा है है:

#include <stdio.h> 
#include <sys/ioctl.h> 
int main() 
{ 
int pid; 
FILE *fp; 
fp = fopen("test.txt","w"); 
char *buff = malloc(1024); 
int fd[2]; 
int count = 0 ; 
pipe(fd); 
pid = fork(); 
     if(pid == 0) 
     { 
       close(fd[1]); 

       int i = 0; 

       while (i < 10) 
       { 
        fprintf(fp,"\n TIME before read: %s \n",__TIME__); 
        read(fd[0], buff+i, 1); 
        ++ i; 
       } 

       fprintf(fp,"Full message received!\nbuffer: %s\n TIME after read %s\n", buff, __TIME__); 
     } 
     else{ 
       close(fd[0]); 
       sleep(10); //delay caused by application specific code replaced with sleep 
       write(fd[1],"THIS is it",10); 
     } 
fclose(fp); 
return 0; 
} 
+0

Thats सही है, लेकिन माता-पिता चर आकार डेटा हर बार लिखते हैं, thats क्यों मैं ioctl का इस्तेमाल किया है पाइप पर डेटा का आकार पाने के लिए। क्या मैं पाइप पर प्राप्त डेटा तक ioctl को अवरुद्ध कर सकता हूं? –

+0

@Ajay No, 'ioctl()' को अवरोधित करने के कोई तरीके नहीं हैं। –

+1

@Ajay ईमानदारी से यदि आकार महत्वपूर्ण है तो मैं इस जानकारी के लिए 'ioctl()' का उपयोग * के खिलाफ दृढ़ता से सुझाव दूंगा। जब तक आप रीड-ऑप के साथ अनुवर्ती नहीं होते तब तक जब तक आप पाइप के दूसरे छोर से लिखे गए अधिक डेटा के कारण आकार पहले ही अमान्य हो सकते हैं तब तक आप इसे तब तक आमंत्रित करते हैं। यदि आप माता-पिता को भेजने वाले num-bytes को पढ़ना चाहते हैं, तो अपने * प्रोटोकॉल * का वह हिस्सा बनाएं (उदाहरण के लिए पहले चार बाइट 32-बिट नेटवर्क-बाइट-ऑर्डर संदेश-लंबाई हैं)। – WhozCraig

1

मुझे लगता है कि

ioctl(fd[0], FIONREAD, &count); 
the count is 0. 

read(fd[0], buff, count) will get no data. 

try 
read(fd[0], buff, 10) 
+0

मैंने पाइप के अंत में डेटा के आकार को निर्धारित करने के लिए ioctl का उपयोग किया है क्योंकि मूल प्रक्रिया द्वारा भेजा गया डेटा परिवर्तनीय लंबाई है। –

+0

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

+0

@WhozCraig क्या कोई तरीका है ताकि, ioctl (xxxx) फ़ंक्शन तब तक इंतजार कर रहा है जब तक पाइप के अंत में डेटा उपलब्ध न हो, जैसा कि पढ़ा जाता है() डेटा उपलब्ध होने तक प्रतीक्षा करता है। –