当前位置: 首页 > 面试题库 >

管道,dup2和exec()

蔚宏大
2023-03-14
问题内容

我必须编写一个可以运行管道的外壳。例如ls -l | wc -l“” 这样的命令。我已成功解析了用户给出的命令,如下所示:

“ ls” = firstcmd

“ -l” = frsarg

“ wc” = scmd

“ -l” = secarg

现在,我必须使用两个fork,因为命令分别是两个和一个管道。我为执行命令编写的代码块如下:

pid_t pid;
int fd[2];

pipe(fd);
pid = fork();

if(pid==0)
{        
    dup2(fd[WRITE_END], STDOUT_FILENO);
    close(fd[READ_END]);
    execlp(firstcmd, firstcmd, frsarg, (char*) NULL);
}
else
{ 
    pid=fork();

    if(pid==0)
    {
        dup2(fd[READ_END], STDIN_FILENO);
        close(fd[WRITE_END]);
        execlp(scmd, scmd, secarg, (char*) NULL);
    }
}

因此,当我运行外壳程序并输入命令ls -l | wc -l(例如)时,执行程序的结果不会显示,但外壳程序将继续正常运行。

奇怪的是,仅当我用“ exit”或“ ^ C”终止shell时,命令的结果才会显示。

该输出有什么问题?输入命令后为什么没有立即显示?


问题答案:

您需要关闭父进程和子进程中的所有管道描述符(在子进程中重复之后)。在您的代码中,主要问题在于,该wc进程不会退出,因为仍然有写程序存在(因为父进程尚未关闭写端)。更改如下所示。我还在waitpid父进程中添加了,以等待该wc进程。

pid_t pid;
int fd[2];

pipe(fd);
pid = fork();

if(pid==0)
{
    dup2(fd[WRITE_END], STDOUT_FILENO);
    close(fd[READ_END]);
    close(fd[WRITE_END]);
    execlp(firstcmd, firstcmd, frsarg, (char*) NULL);
    fprintf(stderr, "Failed to execute '%s'\n", firstcmd);
    exit(1);
}
else
{ 
    pid=fork();

    if(pid==0)
    {
        dup2(fd[READ_END], STDIN_FILENO);
        close(fd[WRITE_END]);
        close(fd[READ_END]);
        execlp(scmd, scmd, secarg,(char*) NULL);
        fprintf(stderr, "Failed to execute '%s'\n", scmd);
        exit(1);
    }
    else
    {
        int status;
        close(fd[READ_END]);
        close(fd[WRITE_END]);
        waitpid(pid, &status, 0);
    }
}


 类似资料:
  • dup2 复制文件描述词 相关函数 open,close,fcntl,dup 表头文件 #include<unistd.h> 定义函数 int dup2(int odlfd, int newfd); 函数说明 dup2()用来复制参数oldfd所指的文件描述词,并将它拷贝至参数newfd后一块返回。若参数newfd为一已打开的文件描述词,则newfd所指的文件会先被关闭。dup2()所复制的文

  • 我有一个azure构建管道和发布管道。我在发布构建工件中面临问题。在构建管道中,发布构建工件被正确地创建在默认的“drop”目录中。 当我在发布管道中下载该工件时,发布文件正在服务抛出错误的中下载 您没有查看此目录或页面的权限。 这意味着我的发布工件没有在“home/wwwroot”目录中下载。 构建管道 释放管道 我错过了什么?

  • 问题内容: 我想通过python从目录中调用脚本(它们是可执行的shell脚本)。 到现在为止还挺好: 现在我想要的是:假设我有一个具有启动功能的bash脚本。我从那里打电话 回声“某事” 现在,我想看看sys.stdout和退出代码上的回显。我相信您可以使用.communicate()执行此操作,但是我的操作不符合我的预期。 我究竟做错了什么? 任何帮助深表感谢 问题答案: 授予http://d

  • 无状态管道是纯粹的功能,通过输入数据流动而不记住任何东西或引起可检测的副作用。 大多数管道是无状态的。 我们使用的CurrencyPipe和我们创建的长度管是无状态管的示例。 状态管道是能够管理它们转换的数据的状态的管道。 创建HTTP请求,存储响应并显示输出的管道是有状态的管道。 有状态管道应谨慎使用。 Angular 2提供 ,这是有状态的。 View Example 实现有状态管道 // n

  • 传递参数 链接管道 我们可以将多个管道连接在一起,以便在一个表达式中使用多个管道。

  • 使装饰器包含具有name属性的管道元数据。 此值将用于在模板表达式中调用此管道。 它必须是有效的JavaScript标识符。 实现PipeTransform接口的transform方法。 此方法接受管道的值和任何类型的可变数量的参数,并返回一个变换的(“管道”)值。 import { Component } from '@angular/core'; selector: 'app-root',