2015-12-02 34 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个字节都可以被写这个只写尽可能多的数据。