2014-01-05 63 views
3

進行我在標題中所說的話時,遇到了很大的麻煩。 基本上,我想要一個程序,比如說broadcast.c,它接受來自用戶的輸入,然後將該輸入發送到兩個進程的輸入。 因此,如果將運行此命令: ./broadcast prog1 prog2將一個進程的stdout重定向到兩個進程

它會阻止等待來自用戶的輸入,然後將該輸入發送到prog1和prog2。

現在,我想使用管道,事情是,我不知道如果我必須使用1管道或2管道。

broadcast.c

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

    int main(int argc, char* argv[]) { 
     int fds1[2], fds2[2]; 
     char buffer[120]; 
     pipe(fds1); 
     pipe(fds2); 

     if (fork() == 0) { 
      close(0); 
      dup(fds1[0]); 
      close(fds1[0]); 
      close(fds1[1]); 
      execl(argv[1], argv[1], NULL); 
     } 

     if (fork() == 0) { 
      close(0); 
      dup(fds2[0]); 
      close(fds2[0]); 
      close(fds2[1]); 
      execl(argv[2], argv[2], NULL); 
     } 

     while(read(0, buffer, 120) != 0) { 
      printf("lido: %s\n", buffer); 
      write(fds1[0],buffer,120); 
      write(fds2[0],buffer,120); 
     } 

     close(1); 
     dup(fds1[1]); 
     dup(fds2[1]); 
     exit(0); 
    } 

我知道這並不工作,它可能會混亂,所以如果你們能幫助我走出這將是巨大的。

現在我只是想,當我做: ./broadcast PROG1 PROG2 用戶輸入:你好

輸出是: PROG1說:你好! prog2說:你好!

基本上PROG1和PROG2只是打印使用的FD 0

+0

谷歌「UNIX三通」。 – cHao

+0

嗡有趣。對此不知道。但是可以用簡單的叉子和嘟嘟來完成嗎? – luispcosta

+0

不是沒有一些代碼來讀取輸入FD並將數據寫入每個輸出FD,據我所知。 – cHao

回答

0

我想要一個程序,比如說broadcast.c,它接受來自用戶的輸入,然後將該輸入發送給兩個進程的輸入。所以,如果將運行此命令:./broadcast prog1 prog2

您可以實現使用bashbroadcast命令:

$ tee >/dev/null >(prog1) >(prog2) 

tee從標準輸入讀取,並將其發送到prog1prog2。默認情況下,tee將stdin複製到標準輸出,因此使用>/dev/null來抑制它。

還有來自moreutils packagepee命令:

$ pee prog1 prog2 

它確實正是你想要的。它使用popen()來運行子進程。實現很簡單,這裏是整個源代碼(pee.cgit://git.kitenet.net/moreutils):

#include <stdlib.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

/* Licensed under the GPL 
* Copyright (c) Miek Gieben, 2006 
*/ 

/* like tee(1), but then connect to other programs using 
* pipes _and_ output to standard output 
*/ 

int 
close_pipes(FILE **p, size_t i) 
{ 
    int ret=EXIT_SUCCESS; 
    size_t j; 
    for (j = 0; j < i; j++) { 
     int r = pclose(p[j]); 
     if (WIFEXITED(r)) 
      ret |= WEXITSTATUS(r); 
     else 
      ret |= 1; 
    } 
    return ret; 
} 

int 
main(int argc, char **argv) { 
    size_t i, r; 
    FILE **pipes; 
    char buf[BUFSIZ]; 

    pipes = malloc(((argc - 1) * sizeof *pipes)); 
    if (!pipes) 
     exit(EXIT_FAILURE); 

    for (i = 1; i < argc; i++) { 
     pipes[i - 1] = popen(argv[i], "w"); 
     if (!pipes[i - 1]) { 
      fprintf(stderr, "Can not open pipe to '%s\'\n", argv[i]); 
      close_pipes(pipes, argc); 

      exit(EXIT_FAILURE); 
     } 
    } 
    argc--; 

    while(!feof(stdin) && (!ferror(stdin))) { 
     r = fread(buf, sizeof(char), BUFSIZ, stdin); 
     for(i = 0; i < argc; i++) { 
      if (fwrite(buf, sizeof(char), r, pipes[i]) != r) { 
       fprintf(stderr, "Write error to `%s\'\n", argv[i + 1]); 
       close_pipes(pipes, argc); 
       exit(EXIT_FAILURE); 
      } 
     } 
    } 
    exit(close_pipes(pipes, argc)); 
} 
+0

這工作。謝謝 – luispcosta

+0

'pee'很有趣,但它不是標準設施,你必須安裝它(並且有可能安裝它)。源代碼很有趣,但它不是最好的開始 - 如果@ user3162721的目的是爲了學習一些東西?那麼也許最好是嘗試修正上面的代碼並解釋他出了什麼問題 - 這就是我的嘗試。 – TMS

0

問題閱讀是流只能去一個目的地。您需要打開兩個流並將其發送到每個目的地,並且我不知道要做到這一點。

可能最簡單的是讓prog1只是通過它接收到的任何輸入並將其發送到輸出上,然後你可以將它添加到鏈的中間,並且對其他進程是有效的。

要展開:

在PROG 1 - 每當它接收在stdin輸入 - 它以及處理其輸出在stdout相同的數據。這意味着您可以將其添加到鏈條broadcast | prog1 | prog2中,數據將傳遞到prog2以及由prog1處理。

+0

Did not understand your answer:s – luispcosta

+0

我增加了一些,看看是否有幫助 –

1

它可以在外殼很容易做到:

FIFO_FILE=/tmp/fifo$$ 
mkfifo $FIFO_FILE 
cat $FIFO_FILE | prog1 & 
cat | tee $FIFO_FILE | prog2 
wait # wait for everything to finish 
rm -f $FIFO_FILE 

如果你堅持的C代碼...有我在你的代碼中發現這麼多的問題:

  • 欺騙對方(0而不是1)
  • 關閉子進程中的其他管道
  • 你應該處理返回值read,實際讀取的字節數和 - pas它S到write功能
  • 必須關閉管道孩子的兩端父
  • 家長應事後
  • unnecesasry dup2調用在程序

年底從數量關閉其管道我發現你看不懂它(抱歉...)。但基本上我必須讚揚你 - 你創建了2個管道和while循環,這個程序的核心幾乎是正確的。我建議你開始學習的小例子一步一步:

Linux Documentation Project - pipes in C

這寶貴的資源,將教你如何做管道,如何等重定向

這是我嘗試修復您的代碼:

int main(int argc, char* argv[]) { 
    int fds1[2], fds2[2]; 
    char buffer[120]; 
    int size; 

    pipe(fds1); 
    pipe(fds2); 

    if (fork() == 0) { 
     close(0); 
     dup(fds1[1]); 
     close(fds1[0]); 
     close(fds1[1]); 
     close(fds2[0]); 
     close(fds2[1]); 
     execl(argv[1], argv[1], NULL); 
    } 

    if (fork() == 0) { 
     close(0); 
     dup(fds2[1]); 
     close(fds1[0]); 
     close(fds1[1]); 
     close(fds2[0]); 
     close(fds2[1]); 
     execl(argv[2], argv[2], NULL); 
    } 

    close(fds1[1]); 
    close(fds2[1]); 

    while((size = read(0, buffer, 120)) != 0) { 
     printf("lido: %s\n", buffer); 
     write(fds1[0],buffer,size); 
     write(fds2[0],buffer,size); 
    } 

    close(fds1[0]); 
    close(fds1[0]); 

    exit(0); 
} 

請注意,您應該通過檢查-1返回值和errno被perror處理所有的系統調用!

+0

謝謝,但我真的必須在c代碼xD。 +1在做殼壽 – luispcosta

+0

在另外兩個程序中,我應該只讀從FD 0? 編輯:是的,它是一種家庭作業。 – luispcosta

+0

@ user3162721是 - 當他們收到他們的輸入時就是這樣。 – TMS

相關問題