0

我编写了一个程序,在 Linux 终端中使用 ls 命令来读取文件夹的内容,并使用我的 C 程序将 ls 中的文本写入屏幕。这是我写的代码:

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

int main()
{
    int pipe_ends[2];
    if(pipe(pipe_ends)) 
    {
        printf("Could not create pipe\n");
        return -1;
    }
    pid_t pid = fork();
    if(pid < 0)
    {
        perror("fork");
        exit(1);
    }
    if(!pid)
    {
        dup2(pipe_ends[0],1);
        char* args[3];
        args[0] = "/bin/ls";
        args[1] = "-l";
        args[2] = NULL;
        execv("/bin/ls",args);
        printf("something went wrong\n");
    }

    char buff[10240];
    int count = read(pipe_ends[1],buff,10240);
    buff[count] = '\0';
    printf("here goes nothing......\n");
    printf("%s",buff);
    return 0;   
}

我为这个程序得到的输出是:

here goes nothing......
od@od-Inspiron-N5110:~/Documents/work/new/CO/project1$ /bin/ls: write error: Bad file descriptor

od@od-Inspiron-N5110:~/Documents/work/new/CO/project1$

似乎在写作之前已经完成了阅读。但我认为阅读是阻塞的。请帮我在这里找到错误。

提前致谢。

4

2 回答 2

1

您必须关闭管道的未使用端——尤其是父进程中管道的写端,因为父进程中的管道read()不会获得 EOF,而父进程的写端仍然打开。此外,您需要从管道 ( ) 的读取端读取,并将管道pipe_ends[0]的写入端复制到ls.

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

int main(void)
{
    int pipe_ends[2];
    if (pipe(pipe_ends))
    {
        printf("Could not create pipe\n");
        return -1;
    }
    pid_t pid = fork();
    if (pid < 0)
    {
        perror("fork");
        exit(1);
    }
    if (pid == 0)
    {
        dup2(pipe_ends[1], 1);
        close(pipe_ends[0]);
        close(pipe_ends[1]);
        char *args[3];
        args[0] = "/bin/ls";
        args[1] = "-l";
        args[2] = NULL;
        execv("/bin/ls", args);
        printf("something went wrong\n");
        return 1;
    }

    close(pipe_ends[1]);
    char buff[10240];
    int count = read(pipe_ends[0], buff, 10240);
    buff[count] = '\0';
    printf("here goes nothing (count = %d)......\n", count);
    printf("%s", buff);
    return 0;
}

代码在错误报告(有时它用于printf()写入标准输出;有时,它用于perror()写入标准错误)和退出(有时使用return -1;,有时使用exit(1);——我添加了一个return 1;以确保子进程不如果执行失败,则不会最终读取内容ls)。

于 2014-01-19T05:25:41.893 回答
0

你遇到了三个问题:

  1. 来自手册页:该数组pipefd用于返回两个引用管道末端的文件描述符。pipefd[0]指管道的读取端。pipefd[1]指管道的写端。pipefd[0]用来写作和pipefd[1]阅读。那是行不通的。这是EBADF(坏文件描述符)错误的根本原因。如果您想要双向性,请使用socketpair()

  2. 当你fork(),你需要关闭你不需要的文件描述符。那是管道的另一端。

  3. 我相信你应该close()在你之前使用 fd dup2,尽管手册页并不明确。在这种情况下,您使用之前close()存在的.STDOUTdup2()

这是一个有效的修订版本(进行了最小的修改以使其与注释一起工作,您可以做更多的事情来使其完美):

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

int
main ()
{
  int pipe_ends[2];
  if (pipe (pipe_ends))
    {
      printf ("Could not create pipe\n");
      return -1;
    }
  pid_t pid = fork ();
  if (pid < 0)
    {
      perror ("fork");
      exit (1);
    }
  if (!pid)
    {
      close (1); /* close previous stdout */
      /* dup write end of pipe */
      dup2 (pipe_ends[1], 1);
      /* close read end */
      close (pipe_ends[0]);
      char *args[3];
      args[0] = "/bin/ls";
      args[1] = "-l";
      args[2] = NULL;
      execv ("/bin/ls", args);
      printf ("something went wrong\n");
    }

  close (pipe_ends[1]); /* close write end of pipe */

  char buff[10240];
  int count = read (pipe_ends[0], buff, 10240);
  buff[count] = '\0';
  printf ("here goes nothing......\n");
  printf ("%s", buff);
  return 0;
}

布丁的证明:

amb@nimrod-ubuntu:~/so$ ./p
here goes nothing......
total 32
-rwxrwxr-x 1 amb amb 8889 Jan 19 09:19 p
-rw-rw-r-- 1 amb amb  853 Jan 19 09:19 p.c
-rwxrwxr-x 1 amb amb 8456 Jan 18 20:47 test
-rw-rw-r-- 1 amb amb  243 Jan 18 20:47 test.c
于 2014-01-19T09:27:57.347 回答