首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >execl()似乎不能从stdin中读取

问execl()似乎不能从stdin中读取
EN

Stack Overflow用户
提问于 2015-12-16 08:59:08
回答 3查看 2.1K关注 0票数 2

我正在尝试用c语言重现这个命令:

代码语言:javascript
复制
ls | wc > output.txt

为此,我编写了以下程序:

代码语言:javascript
复制
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>

int main()
{
    pid_t lsFork, wcFork;
    int tube[2];
    pipe(tube);

    lsFork = fork();
    if(lsFork == 0) // ls command
    {
        close(tube[0]);
        dup2(tube[1], STDOUT_FILENO);
        close(tube[1]);
        if(execl("/usr/bin/ls", "ls", NULL) == -1)
            perror("Cannot execute ls");
    }
    else
    {
        wcFork = fork();
        if(wcFork == 0)  // wc command
        {
            sleep(1);
            int file = open("output.txt", O_WRONLY | O_CREAT);
            if(file == -1)
                perror("Cannot open output.txt");

            close(tube[1]);
            dup2(tube[0], STDIN_FILENO);
            close(tube[0]);
            dup2(file, STDOUT_FILENO);
            close(file);

            /*char buffer[BUFSIZ];
            read(STDIN_FILENO, buffer, BUFSIZ);
            write(STDOUT_FILENO, buffer, BUFSIZ);*/

            if(execl("/usr/bin/wc", "wc", NULL) == -1)
                perror("Cannot execute wc");

            close(STDOUT_FILENO);
        }
        else // parent
        {
            int status;
            waitpid(lsFork, &status, 0);
            waitpid(wcFork, &status, 0);
        }
    }

    return EXIT_SUCCESS;
}

但是,程序不会退出。根据htop的说法,wc命令阻塞了程序。为了理解这种行为,我写了一段代码( execl()之前的代码行注释),我不明白这是怎么回事,而不是execl()。我是不是在调用这个函数的时候忘记了什么?

EN

回答 3

Stack Overflow用户

发布于 2015-12-16 09:49:21

父进程仍然有打开的管道,所以wc正在等待,以防父进程决定写入内容( wc需要对其进行计数)。

同时关闭父管道中管道的两端:

代码语言:javascript
复制
    else // parent
    {
        int status;
        close(tube[0]); // <---
        close(tube[1]); // <---
        waitpid(lsFork, &status, 0);
        waitpid(wcFork, &status, 0);
    }
票数 1
EN

Stack Overflow用户

发布于 2015-12-16 15:08:29

不要在你能轻易做到的时候把事情复杂化。尝试下面更简单的代码&看看您是否能理解任何东西。

代码语言:javascript
复制
int main(){
    int tube[2];
    int fID;
    pipe(tube);
    if (fork() == 0){
      // this is the child process
      close(tube[0]); // reading end of the pipe
      dup2(tube[1], 1); // stdout ---> pipe writing end
      execlp("ls", "ls", NULL);
    }else{
      if (fork() == 0){
        //umask(0022);
        fID = open("sample.txt", O_WRONLY | O_CREAT, 0644);
        close(tube[1]); // writing end of the pipe
        dup2(tube[0], 0);  // stdin ----> pipe reading end
        dup2(fID, 1);
        execlp("wc", "wc", NULL);
      }
    }
  return 0;
}

注意如果代码的目的仅仅是实现上面提到的管道,那么你不需要实现任何等待机制。操作系统将自动杀死所有僵尸子进程。此外,execlp("wc", "wc", NULL);会自动阻止程序结束。因此它不会提前退出。

票数 1
EN

Stack Overflow用户

发布于 2015-12-16 09:41:10

您还需要关闭父进程中管道的写入端。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34302259

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档