2015-12-02 33 views
1

我正在創建一個帶有服務器端客戶端的C程序。使用FIFO(名稱管道)重定向stdin

我一直在試圖將標準輸入重定向到我創建的命名管道,並且設法將客戶端寫入管道。在服務器端,我打開了相同的管道,關閉了stdin,並使用dup(用dup2嘗試)將管道重定向到stdin。

我必須使用函數getline讀取輸入。問題是它會正確讀取第一個輸入,但在它之後只收到空值。我會在問題中添加一個示例。

服務器:

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 


main() { 
    char* str; 
    size_t size=0; 
    int pshell_in; 

    unlink("/tmp/par-shell-in"); 
    if(mkfifo("/tmp/par-shell-in", 0777) < 0){ 
     fprintf(stderr, "Error: Could not create pipe\n"); 
     exit(-1); 
    } 

    if((pshell_in = open("/tmp/par-shell-in", O_CREAT | O_RDONLY, S_IRUSR)) < 0){ 
     fprintf(stderr, "Error: Failed to open file\n"); 
     exit(-1); 
    } 

    dup2(pshell_in, 0); 
    close(pshell_in); 



    while(1) { 
     if (getline(&str, &size, stdin)<0) { 
      printf("Oh dear, something went wrong with getline()! %s\n", strerror(errno)); 
      return -1; 
     } 

     printf("%s", str); 
    } 
} 

*我知道它的空,因爲我已經與讀取印刷它(而不是重定向),並將其打印(空)。

客戶端:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/stat.h> 
#include <string.h> 
#include <fcntl.h> 

#define VECTORSIZE 7 

int main() { 

    char* buf; 
    int pshell_in; 
    size_t size=0; 

    if((pshell_in = open("/tmp/par-shell-in", O_WRONLY, S_IWUSR)) < 0){ 
     fprintf(stderr, "Error: Failed to open file\n"); 
     exit(-1); 
    } 

    printf("%d\n", pshell_in); 

    while(1) { 
     if (getline(&buf, &size, stdin) < 0) { 
      return -1; 
     } 

     write(pshell_in, buf, 256); 
    } 
} 
  • 我懷疑它的正確的,因爲如果我用閱讀客戶端(與O_RDWR O_WRONLY更換)它打印我鍵入它的字符串。

任何人都可以幫助我這個嗎?

回答

2

FIFO是有趣的事情。如果一個進程試圖打開一個進行讀取,它將會阻塞,直到有一個進程打開它進行寫入。相反,如果一個進程試圖打開一個進行寫入,它將會阻塞,直到有一個進程打開它進行讀取。但是,多個進程可以打開它進行讀取或寫入。當沒有更多的進程開放閱讀時,寫入將失敗;當沒有更多的進程打開寫入時,讀取將失敗。當操作失敗時,必須關閉並重新打開FIFO才能重新繼續處理數據。

我強烈懷疑您因爲這些行爲而遇到問題。

此外,您的客戶端編寫的代碼是可疑的;你沒有注意到有多少數據被讀取。您有:

while(1) { 
    if (getline(&buf, &size, stdin) < 0) { 
     return -1; 
    } 
    write(pshell_in, buf, 256); 
} 

如果象是可能的,你在該行讀取輸入少於256個字符,那麼它很可能是你去寫超出被getline()分配的數組的邊界。一些甚至大部分數據都是空字節也是明顯可能的。但是,您在服務器中看到的(null)通常表示您試圖打印字符串,但通過printf()空指針。無論發生什麼事情,大部分都是未定義的行爲,這是一件壞事,應該不惜一切代價避免。

你應該有更多的東西一樣:

ssize_t nbytes; 

while ((nbytes = getline(&buf, &size, stdin)) > 0) 
{ 
    if (write(pshell_in, buf, nbytes) != nbytes) 
    { 
     fprintf(stderr, "Short write to FIFO\n"); 
     break; 
    } 
} 
free(buf); 

說明如何爲讀取,並且不認爲256個字節都可以被寫這個只寫儘可能多的數據。