如何在管道中的数据上调用UNIX排序命令

时间:2015-01-07 00:37:16

标签: c unix systems-programming

我正在创建一个C程序,并且我正在为进程间通信单独分叉进程之间设置一个管道。

第一个进程已将我需要的数据写入管道。 但是,当第二个进程从管道读取时,我试图执行该进程以成为UNIX排序命令。我想以某种方式对管道中的数据进行排序。

如何在管道上调用sort?在命令行上,我可以通过提供文件名进行排序,以排序为命令行参数,例如" sort -r MyFileToSort"。我知道管道基本上被认为是文件,但它们只是用它们的文件描述符来描述,据我所知,排序不知道如何处理fd。

感谢您提供任何帮助/反馈

2 个答案:

答案 0 :(得分:0)

在这种情况下,您根本不需要传递sort任何参数来指定输入源或输出接收器。相反,在exec之前,您应该根据需要将管道的文件描述符附加到其stdin(FD 0,如果从管道接收数据)或stdout(FD 1,如果将数据写入管道)。

请参阅dup2()调用,该调用可让您为此目的设置复制FD的目的地。正如@JonathanLeffler指出的那样,你需要确保在执行exec之前关闭原始的FD(在将它们复制到你想要的数字之后)。


由于您在评论中澄清了您的目标是写入文件,因此在调用exec之前将FD 1附加到该目标文件,并将FD 0附加到管道的输出端包含输入。

答案 1 :(得分:0)

int p[2];
if (pipe(p) != 0) ...report error and do not continue...
pid_t pid = fork();
if (pid < 0) ...report error, close pipe descriptors, and do not continue...
if (pid == 0)
{
    /* Child - becomes sort */
    dup2(p[0], 0);
    close(p[0]);
    close(p[1]);
    int fd = open("output-file", O_CREAT | O_EXCL | O_WRONLY, 0644);
    if (fd < 0) ...report error and exit...
    dup2(fd, 1);
    close(fd);
    execlp("sort", "sort", (char *)0);
    ...report error and exit...
}
else
{
    /* Parent - writes data to sort */
    close(fd[0]);
    ...write data to fd[1]...
    close(fd[1]);
    int status;
    int corpse;
    while ((corpse = wait(&status)) > 0 && corpse != pid)
        ...consider reporting which child died...
    ...consider reporting sort status...
    ...continue with the rest of the program...
}

您可以决定是否报告与dup2()失败或close()失败相关的错误。除了报告问题并退出之外,在任何一种情况下你都无能为力。除非有人通过不提供标准输入,标准输出和标准错误(或程序中其他地方已关闭任何标准通道)使您的程序遭受残酷和不寻常的惩罚,否则管道和文件描述符不能标准的I / O描述符,因此关闭是安全的。如果您不确定您的用户有多恶心,您可以保护关闭:

if (p[0] > FILENO_STDERR)
    close(p[0]);

这通常是不必要的偏执(但尝试缺少标准I / O的程序会很有趣)。