Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何对管道中的数据调用UNIX排序命令_C_Unix_Systems Programming - Fatal编程技术网

C 如何对管道中的数据调用UNIX排序命令

C 如何对管道中的数据调用UNIX排序命令,c,unix,systems-programming,C,Unix,Systems Programming,我正在创建一个C程序,并用它在单独分叉的进程之间设置一个管道,用于进程间通信 第一个进程已将我需要的数据写入管道。 但是,当第二个进程从管道中读取数据时,我试图执行该进程,使其成为UNIX排序命令。我想对管道中的数据调用sort 我怎样才能在管道上呼叫分拣?在命令行上,我可以通过提供要排序的文件名作为命令行参数进行排序,例如“sort-r MyFileToSort”。我知道管道本质上被认为是文件,但它们只由文件描述符描述,据我所知,sort不知道如何处理fd 感谢您的帮助/反馈在这种情况下,您根

我正在创建一个C程序,并用它在单独分叉的进程之间设置一个管道,用于进程间通信

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

我怎样才能在管道上呼叫分拣?在命令行上,我可以通过提供要排序的文件名作为命令行参数进行排序,例如“sort-r MyFileToSort”。我知道管道本质上被认为是文件,但它们只由文件描述符描述,据我所知,sort不知道如何处理fd


感谢您的帮助/反馈

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

请参阅
dup2()
调用,该调用允许您为此目的设置要将FD复制到的目标。正如@JonathanLeffler所指出的,在调用exec之前,您需要确保关闭原始的FDs(将它们复制到您想要的号码之后)


由于您已在注释中阐明,您的目标是写入文件,因此在调用
exec
之前,您应该将FD 1附加到该目标文件,并将FD 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...
}

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

您已经尝试了什么?这可能会有所帮助:@martinclayton,为什么这里需要命名管道?您只需根据需要将
mkpipe()
返回的FD附加到stdin或stdout即可。@Charles help!=顺便说一下,@ Paulver,……顺便说一下,如果你不清楚如何设置这一点,你可以考虑阅读<代码> > Struts BASH-C 'GealTyPATA数据>排序> MyOutPutfile(),看看shell是如何完成任务的,并在 Exc*()之前关闭未使用的文件描述符。call——在本例中,来自
pipe()
的两个文件描述符。谢谢,我将标准输入重定向到了管道的读取器,现在调用sort而不指定文件就可以了。我仍然有一个小问题,但是这个问题的上下文已经回答了谢谢你的代码示例。我认为sort必须显式地传递一个文件名,但我看到将stdin重定向到管道并只调用sort worksMany,但决不是all,Unix程序作为“过滤器”工作,在没有文件名的情况下读取标准输入并写入标准输出。您可以使用:
execlp(“排序”、“排序”、“-o”、“输出文件”、(char*)0)而不是在代码中执行I/O重定向。这会导致
排序
写入
输出文件
。通常,它允许
sort
写入其一个输入文件;如果你接受了这个改变,你只是把这个选项当作一个副作用。如果你有排序选项,你应该考虑<代码> ExcVP()< <代码> > <代码>执行>(<)>代码>,而不是<代码> ExcLp()<代码>;您可以通过这种方式拥有可变长度的参数列表。
if (p[0] > FILENO_STDERR)
    close(p[0]);