简单的Linux管道程序,收不到数据

Posted

技术标签:

【中文标题】简单的Linux管道程序,收不到数据【英文标题】:Simple Linux pipe program, data is not received 【发布时间】:2012-09-28 13:41:17 【问题描述】:

我正在编写一个简单的 Linux C 程序,以帮助我更好地理解 IPC,现在我正在尝试使用管道构建它。我有一个在两个不同终端中运行的单一代码库windows 作为两个不同的可执行文件(因此它们可以相互通信)。但是我没有做正确的事情,因为我从来没有读取任何数据,但我不确定是什么......

注意这不是完整的代码,我删掉了输出/输入/验证以节省空间。但在下面程序的 cmets 中注明了。

void main()

  int pipefd[2], n;
  char input = 0;
  char buffer[100] = 0;
  char outpipe[100] = 0;

  if(pipe(pipefd) < 0) 
    printf("FAILED TO MAKE PIPES\n");
    return;
  

  printf("Starting up, read fd = %d, write fd = %d\n", pipefd[0],pipefd[1]);

  do 
    //print menu options (send message, get message, get my fd, 
    // set a fd to talk to, quit)

    // if "send a message":
    
      printf("What would you like to send?\n");
      fgets(buffer, 100, stdin);
      write(pipefd[1], buffer, strlen(buffer));
    
    //else if "read a message":
    
      if(open(outpipe, 0) < 0)
          printf("Couldn't open the pipe!\n");
      else 
        n = read(outpipe, buffer, 100);
        printf("I got a read of %d bytes\nIt was %s\n",n, buffer);
        close(outpipe);
      
    
    //else if "get my file descriptor":
      printf("My fd tag is: /proc/%d/fd/%d\n", (int)getpid(), pipefd[0]);
    //else if "set a file descriptor to talk to":
    
      printf("What is the pipe's file descriptor?\n");
      fgets(outpipe, 100, stdin);
      n = strlen(outpipe) - 1;
      outpipe[n] = '\0';
    
   while (input != 'Q');
return;

我知道管道已成功创建,我已验证文件描述符已到位:

lr-x------ 1 mike users 64 Sep 26 23:31 3 -> pipe:[33443]
l-wx------ 1 mike users 64 Sep 26 23:31 4 -> pipe:[33443]

看起来权限正常(在管道 3 上读取,在管道 4 上写入)。

我就是这样使用它的:

//terminal 1
Pick an option:
3
My fd tag is: /proc/8956/fd/3

//terminal 2
Pick an option:
4
What is the pipe's file descriptor?
/proc/8956/fd/3

Pick an option:
1
What would you like to send?
hello

//terminal 1
Pick an option:
2
I got a read of -1 bytes
It was 

我在这里做的有什么明显的错误吗?我的读取总是得到“-1”返回值...

【问题讨论】:

如果您还没有,请查看 Beej 的指南:beej.us/guide/bgipc 我很惊讶你的程序竟然可以编译,因为像对文件的 readclose 这样的调用是错误的。 @JoachimPileborg - 是的,编译得很好,也没有警告。我想它对于 gcc 来说已经足够接近了。调用不正确怎么办? @Mat - 我打印了它,它是正确的。 strlen()-1 设置为 '\0' 是为了摆脱 fgets 附加的'\n' 其他几件事,你永远不会改变input,所以它会永远循环;而且你永远不会说 在哪里 你得到了-1 返回值;最后,如果出现错误,您不会打印错误。使用例如perror 打印可读消息。 【参考方案1】:

您似乎误解了管道的工作原理。管道是一个匿名文件描述符,它不是文件系统中的文件。 /proc/&lt;pid&gt;/fd中的文件你不用关心。

这里是你正在尝试做的重写:

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

int main(void)

    int pipefds[2];
    char input[128];
    char output[128];
    ssize_t nread;

    if (pipe(pipefds) == -1)
    
        perror("Could not create pipe");
        return EXIT_FAILURE;
    

    printf("Enter input: ");
    if (fgets(input, sizeof(input), stdin) == NULL)
    
        perror("Could not read input");
        return EXIT_FAILURE;
    

    /* "Remove" newline from input */
    if (input[strlen(input) - 1] == '\n')
        input[strlen(input) - 1] = '\0';

    /* Now write the received input to the pipe */
    if (write(pipefds[1], input, strlen(input) + 1) == -1)
    
        perror("Could not write to pipe");
        return EXIT_FAILURE;
    

    /* Now read from the pipe */
    if ((nread = read(pipefds[0], output, sizeof(output))) == -1)
    
        perror("Could not reaf from pipe");
        return EXIT_FAILURE;
    

    /* We don't need to terminate as we send with the '\0' */

    printf("Received: \"%s\"\n", output);

    return EXIT_SUCCESS;

【讨论】:

你是对的。我确实对我试图做的事情感到困惑,因为我误解了管道。但我并不是要让程序与自己或子进程对话。我想我真正想要的是一个命名管道,或 FIFO,让他们互相交谈 @Mike 那我建议你看看mkfifo(3)mkfifo(1) 甚至不知道mkfifo(),这是一个很棒的工具。我正在看的书(和 L0j1k 的链接)使用mknod()。感谢您的帮助!【参考方案2】:

这是您最关心的问题:

./ipctest.c: In function ‘main’:

./ipctest.c:32:9: warning: passing argument 1 of ‘read’ makes integer from pointer without a cast [enabled by default]
/usr/include/unistd.h:361:16: note: expected ‘int’ but argument is of type ‘char *’

./ipctest.c:34:9: warning: passing argument 1 of ‘close’ makes integer from pointer without a cast [enabled by default]
/usr/include/unistd.h:354:12: note: expected ‘int’ but argument is of type ‘char *’

查看某个函数所需的数据类型... :)

【讨论】:

是的,正如 Joachim Pileborg 指出的那样,错误的论点.. 这对我来说是愚蠢的。您使用哪些选项运行 gcc?我没有收到任何警告。 mike@linux-4puc:~&gt; gcc -Werror pipe_tester.c mike@linux-4puc:~&gt; 哇...仍然没有。 (gcc 版本 4.6.2 SUSE Linux)。 有趣!试试gcc -Wall pipe_tester.c 宾果游戏。添加-Wall 告诉我implicit declaration of getpid() read() 和其他人。添加了#include &lt;unistd.h&gt;,现在我收到了参数警告。有趣的是它只用stdio.hstring.h 编译

以上是关于简单的Linux管道程序,收不到数据的主要内容,如果未能解决你的问题,请参考以下文章

Linux:如何正确地将文本通过管道传输到程序中?

Linux 管道

Linux - 进程间通信 - 匿名管道

Linux网络编程学习 ----- 管道(第四章)

Linux之------进程间通信

Linux环境进程间通信:管道及有名管道