2009-11-14 9 views

cevap

25

Kurulumu:

Şimdi
FILE *f = popen("./output", "r"); 
int d = fileno(f); 
fcntl(d, F_SETFL, O_NONBLOCK); 

okuyabilir:

ssize_t r = read(d, buf, count); 
if (r == -1 && errno == EAGAIN) 
    no data yet 
else if (r > 0) 
    received data 
else 
    pipe closed 

ne zaman' yeniden yapıldı, temizleme:

pclose(f); 
+0

Güzel çalışıyor ... teşekkürler! – jldupont

+0

FILE işaretçisi olan boru, doğal olarak arabelleğe alınmış, dosya tanımlayıcısını doğrudan kullanarak, dosya arabelleği içine çekilen bir şeyi kaçırmayacağınız konusunda herhangi bir güvence var mıdır, yoksa bu, istediğiniz sürece garanti edilebilir İlk önce fget/fread/etc'yi arama. – stu

2

Hiç denemediniz, ancak neden dosya tanıtıcılarını fileno() ile yakalayamadığınızı anlamıyorum, engellemeyi engellemek için fcntl() kullanın ve read()/write() kullanın. Denemeye değer.

+0

Bunu yapacağım! Teşekkürler! – jldupont

+2

Bu yordamın çalıştığını doğrulayabilirim. – jldupont

4

popen() içten pipe(), fork(), dup2() ve execve() (çocuk sürecin fds borulara 0/1/2 işaret etmek) çağırır. Bunları kullanmayı düşündünüz mü? Bu durumda, okuduğunuz boruyu fcntl() kullanarak engellememeye ayarlayabilirsiniz.

güncelleme: Burada sadece gösterim amaçlı, bir örnek: Böyle

int read_pipe_for_command(const char **argv) 
{ 
    int p[2]; 

    /* Create the pipe. */ 
    if (pipe(p)) 
    { 
     return -1; 
    } 

    /* Set non-blocking on the readable end. */ 
    if (fcntl(p[0], F_SETFL, O_NONBLOCK)) 
    { 
     close(p[0]); 
     close(p[1]); 
     return -1; 
    } 

    /* Create child process. */ 
    switch (fork()) 
    { 
     case -1: 
      close(p[0]); 
      close(p[1]); 
      return -1; 
     case 0: 
      /* We're the parent process, close the writable part of the pipe */ 
      close(p[1]); 
      return p[0]; 
     default: 
      /* Close readable end of pipe */ 
      close(p[0]); 
      /* Make stdout into writable end */ 
      dup2(p[1], 1); 
      /* Run program */ 
      execvp(*argv, argv); 
      /* If we got this far there was an error... */ 
      perror(*argv); 
      exit(-1); 
    } 
} 
+0

Olmaması gerekenler: eğer (pipe (p) <0) dönüş -1; ? – Aktau

+1

@Aktau Sürümümü daha iyi beğeniyorum. Syscall, başarıya 0 döner. If ifadesi sıfır olmayan için test eder. – asveikau

+1

haklısın, senin versiyonun da tamamen doğru, diğer syscall'ları düşünüyordum! – Aktau