【问题标题】:can not read from pipe with execlp无法使用 execlp 从管道中读取
【发布时间】:2016-02-23 19:55:27
【问题描述】:

对于一个任务,我应该实现 linux 终端。我的终端应该支持带有管道的参数。就像用户可以输入: ls | grep ".cpp" 到目前为止我所做的是:

pid = fork();
if(pid==0)
{
  close(fd[0]);
  dup2(fd[1],1);
  close(fd[1]);
  execlp("/bin/ls","ls");
}
wait(NULL);
pid=fork();
if(pid==0)
{
  close(fd[1]);
  dup2(fd[0],0);
  close(fd[0]);
  execlp("/bin/grep","grep",".cpp");
}

我的第一个孩子工作完美,将 ls 的输出写入之前声明的管道,但是,我的第二个孩子运行 grep,但显然无法从管道获取输入。为什么呢? 当我运行它时,我的输出是 /root/OS $ ls | grep

就这样卡住了

【问题讨论】:

    标签: c++ linux bash pipe exec


    【解决方案1】:

    不要忽略编译器警告:

    $ gcc lol.c
    lol.c: In function ‘main’:
    lol.c:14:5: warning: not enough variable arguments to fit a sentinel [-Wformat=]
         execlp("/bin/ls","ls");
         ^
    lol.c:23:5: warning: missing sentinel in function call [-Wformat=]
         execlp("/bin/grep","grep",".cpp");
         ^
    

    这里是man execlp

    按照惯例,第一个参数应该指向与正在执行的文件关联的文件名。参数列表必须以 NULL 结尾 指针,并且,由于这些是可变参数函数,因此必须将该指针强制转换为 (char *) NULL。

    始终使用-Werror 进行编译,以便在出现警告时编译失败,最好还使用-Wall 以获得所有潜在问题的警告。

    这是您的程序,其中添加了 main 方法和哨兵:

    #include <unistd.h>
    #include <sys/wait.h>
    
    
    int main() {
      int fd[2];
      int pid;
    
      pipe(fd);
      pid = fork();
      if(pid==0)
      { 
        close(fd[0]);
        dup2(fd[1],1);
        close(fd[1]);
        execlp("/bin/ls","ls", NULL);
      }
      wait(NULL);
      pid=fork();
      if(pid==0)
      { 
        close(fd[1]);
        dup2(fd[0],0);
        close(fd[0]);
        execlp("/bin/grep","grep",".cpp", NULL);
      }
      return 0;
    }
    

    这是它现在的运行方式:

    $ gcc -Wall -Werror lol.c -o lol
    $ ./lol
    foo.cpp
    

    【讨论】:

    • 我认为您应该补充一点,对wait() 的调用被 OP 放错了位置。就是这样,如果目录有太多条目,ls 将在写入没有人使用数据的管道时停止。消费者进程应尽快启动,主进程应在整个管道设置正确后等待两者,
    猜你喜欢
    • 1970-01-01
    • 2018-06-05
    • 2015-07-03
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    相关资源
    最近更新 更多