2011-02-12 17 views
5
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 

int 
main(int argc, char **argv) 
{ 
    int pfds[ 2], i; 
    size_t pbytrd; 
    pid_t childpid; 
    char buffer[ 200]; 

    pipe(pfds); 
    if((childpid = fork()) == -1) 
    { 
      perror("fork error: "); 
      exit(1); 
    } 
    else if(childpid == 0) 
    { 
      close(pfds[ 0]); 
      dup2(pfds[1], 1); 
      close(pfds[ 1]); 
      for(i = 0; i < 10; i++) 
       printf("Hello..."); 
      execlp("xterm","xterm","-e","./sample_a", (char *) 0); 
      exit(0); 
} 
else 
{ 

     close(pfds[ 1]); 
     for(; ;) 
     { 
      if((pbytrd = read(pfds[ 0], buffer, sizeof(buffer))) == -1) 
      { 
       perror(" read error: "); 
       exit(1); 
      } 
      else if(pbytrd == 0) 
      { 

       write(fileno(stdout), "Cannot read from pipe...\n", strlen("Cannot read from pipe...\n")); 
       exit(0); 
      } 
      else 
      { 
       write(fileno(stdout), "MESSAGE: ", strlen("MESSAGE: ")); 
       write(fileno(stdout), buffer, pbytrd); 
      } 
     }  
} 
return(0); 

}dup2() ve exec()

Benim sample_a.c kod aşağıda: Yukarıdaki kodda

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 

int 
main(int argc, char **argv) 
{ 
     int i; 
     for(i= 0; i< 10; i++) 
     write(fileno(stdout), "Hello...", strlen("Hello...")); 
    return(0); 
} 

, ne gerçekten yapmak istediğim: 1) Yönlendirme Çocuk işleminden borunun çıktısını alıp ebeveynin borudan okumasını ve bunu stdout'a yazdırmasını sağlayın.

Çocuk işlem çıktısını ("printf") stdout'tan boruya yeniden yönlendirebiliyorum ancak execlp'in alt işlemini, xterm, çıktısını boruya yeniden yönlendiremiyorum.

Bunu bana kimse anlatabilir mi?

cevap

4

xterm bir terminal emülatördür. Sağladığınız programı (sample_a) yürütür, giriş ve çıkışları kendisine bağlar, böylece program kullanıcı girdisini standart girişinde alır ve standart ve hata çıktılarına gönderdiği her şeyi kullanıcıya yazdırır.

Programınız ne yapıyor xterm çıktısını boruya bağlamak ve bunu okumaktır. Ancak xterm bir GUI programıdır, normalde çıktılarına veri yazmaz. Belki de tam olarak ne elde etmeye çalıştığınız tam olarak net değildir.

xterm bölümünü kaldırırsanız, beklediğiniz gibi çalışmalıdır, yani üst işlem, sample_a çıktısına ne yazdığını görecektir.

 execlp("./sample_a", "./sample_a", (char *) 0); 
+0

ile yazabilirim, xterm parçasını çıkarırsam işe yarayacaktır. Üniversite web sitesinden birinde gördüğüm bir programlama sorusu. Alıştırma xterm penceresindeki kullanıcı tarafından giriş kabul edilir ve xterm üzerindeki görüntü çıkışı görüntülenir, ancak herhangi bir hata (perror), çağrıldığı yerden terminal penceresine yazdırılmalıdır. Yani xterm'in terminal penceresine geri dönüş yolu yok mu? Aslında bu büyük problemin küçük bir parçasıdır (5-6 sayfa problemi). Bu yardımcı olur umarım –

1

xterm'ın çıkışı yoktur, bu nedenle herhangi bir yere yönlendirmenin yolu yoktur. xterm bir çocuğu çalıştırır ve çocuğun çıkışını kendisine yönlendirir, bu nedenle çocuğun çıktısını xterm'den başka bir yere yönlendirmek istiyorsanız, bunu xterm'den başlatmanız gerekir. Bunu yapmanın en kolay yolu, xterm'in bir kabuk başlatması ve kabuk yönlendirmesini kullanmasıdır.

execlp("xterm", "xterm", "-e", "/bin/sh", "-c", "./sample_a 2>somewhere", 0); 

uygun bir şeyle somewhere değiştirilmesi: çocuk için sadece Stderr yönlendirmek için, böyle bir şey kullanmayı tercih ediyorum. Orijinal programınızda bunu yakalamak istediğinizi varsayarak, muhtemelen geçici bir fifo'yu tempnam (3) ve mkfifo (3) ile oluşturmak ve ebeveyninizde okumak için açabilirsiniz. Forking'i açmadan önce oluşturmalısınız ve forking'i açtıktan sonra açmanız gerekir, zira açık kabuk bloke edip yazma ucunu açana kadar bloke olur. Açık tamamlandığında, fifo'yu silebilir ve şu anda adlandırılmamış fifo'dan okuyabilirsiniz.

1

Benzer bir durumla karşılaştım. Amacım, xterm ile çalışan çocuk işlemlerinden bazı bilgiler göndermekti. Daha önce de bildirildiği gibi, dup2 kullanamadım. Bunun için bir geçici çözüm, fd'yi xterm dizisi olarak yeni ikiliye aktarmaktır.

A, nedenini dup2 dozları bilmiyorum

main(int argc, char** argv) { 
    int fd = atoi(argv[1]); 
    write(fd, buf,sizeof(buf)); 
}  

fd ayıklamak xterm'den çalışır çocuk süreç Açık (kısalık için hata kontrolleri olmadan) yaklaşımı olduğunu

if (childpid == 0) 
{ 
    /* child closes read*/ 
    close(pipeFD[0]); 
    char writeFD[10]; // do consider space for '\0' 
    /* Extract the write fd and put it in a char buffer 
     make compatible as per execlp args */ 
    sprintf(writeFD, "%d", pipeFD[1]); 
    /* just pass the writeFD as an arg */ 
    execlp("xterm", "xterm", "-e", "./binary", writeFD, (char *) 0)) 

} 
else 
{ 
    /* parent closes write */ 
    close(pipeFD[1]); 
    if((bytesRead = read(pipeFD[0], buf, SIZE)) != -1) 
    { 
     printf("Recieved %s\n", buf); 
     close(pipeFD[0]); 
    } 
} 

önerdi nt xterm ile çalışır, ancak bu geçici çözüm gereksinimi çözer.

1

PipeFD dizisi, bir xterm penceresi oluşturduktan sonra, iki dosya açıklaması içeri ve dışarı kaydeder.Çocuk süreci nereye yazılacağını bilmiyor. Yani dup2 kullanabilirsiniz: Yeni bir bağlantı noktasına eski yazma portu (diğer sayılar da işe) eşler

dup2(pipeFD[1],100); 
close(pipeFD[1]); 

. Ve xterm'de, boruya

write(100,"something you wanna to write").