【问题标题】:sed command using pipes causes infinite loop使用管道的 sed 命令导致无限循环
【发布时间】:2014-04-09 22:51:29
【问题描述】:

所以我正在尝试使用管道来 cat 文件并将 sed 放入名为 newfile.txt 的文件中。目前 cat 命令可以使用 execvp,但是它正在输出到命令显示上。然后程序在执行 sed 命令时进入无限循环。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

char *myargv2[]={"sed", "-e" "s/color/colour/g",  NULL};
char *myargv1[]={"cat", "colorfile.txt", NULL};

main()
{
    int f_des[2];
    int fd[2];
    int pipe(int filedes[2]);
    int file = open("newfile.txt",O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);

    if (file < 0)
        return 1;

    // create a pipe
    // Open a pipe and report error if it fails
    if (pipe(f_des)==-1)
    {
        perror("Pipe");
        exit(2);
    }

    //fork the process
    // Use switch for fork, because parent doesn't need child's pid.
    switch (fork())
    {
    case -1:  // Error
        perror("Fork");
        exit(2);

    case 0:   // Child
        printf("HERE1\n");
        //child will call dup2 to hook standard output to one end of the pipe. Then, execute the cat command using execvp
        dup2(fd[1], fileno(stdout));
        execvp(myargv1[0], myargv1);
        close(fd[1]);
        close(fd[0]);
        perror(myargv1[0]);
        close(fd[1]);
        close(fd[0]);
        printf("HERE12\n");

        exit(3);

    default:  // Parent
    {
        printf("HERE13\n");
        //parent will call dup2 to hook standard input to the other end of the pipe. Then, execute the sed command using execvp
        dup2(fd[0], fileno(stdin));
        execvp(myargv2[0], myargv2);
        perror(myargv2[0]);
        close(fd[1]);
        close(fd[0]);
        printf("HERE14\n");

        //parent will also call dup2 to hook standard output to the file called newfile.txt
        if(dup2(file,0 < 0))
            return 1;
    }

    exit(4);
    }

    return 0;
}

显然我在这里挣扎。谁能指出我做错了什么和/或向我指出如何做到这一点的良好信息来源?

谢谢!

【问题讨论】:

  • 最好先通过网络上容易获得的开始 linux 编程。如果您从第 10 章开始学习,那么您的每个疑问都会清除,并且我认为该程序已出现在第 14 章。检查一次,这对您很有帮助。

标签: c sed exec pipe dup


【解决方案1】:

一个主要问题是您无法决定是使用f_des 还是fd 作为管道文件描述符。你有:

int f_des[2];
int fd[2];
int pipe(int filedes[2]);
…
if (pipe(f_des) == -1)
{
    perror("Pipe");
    exit(2);
}

pipe() 的声明不是个好主意;这就是系统头文件的作用。但严重的问题是您在f_des 中创建管道,然后使用fd

另一个问题是您没有准确地关闭管道文件描述符。您还有大量多余的代码。此代码正常工作:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

static char *myargv2[]={"sed", "-e" "s/color/colour/g",  NULL};
static char *myargv1[]={"cat", "colorfile.txt", NULL};

int main(void)
{
    int fd[2];
    int pipe(int filedes[2]);
    int file = open("newfile.txt",O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);

    if (file < 0)
        return 1;

    if (pipe(fd)==-1)
    {
        perror("Pipe");
        exit(2);
    }

    switch (fork())
    {
    case -1:  // Error
        perror("Fork");
        exit(2);

    case 0:   // Child
        printf("HERE1\n");
        dup2(fd[1], fileno(stdout));
        close(fd[0]);  // Important (in general)
        close(fd[1]);  // Important (in general)
        execvp(myargv1[0], myargv1);
        perror(myargv1[0]);
        printf("HERE12\n");
        exit(3);

    default:  // Parent
        printf("HERE13\n");
        dup2(fd[0], fileno(stdin));
        close(fd[0]);  // Crucial
        close(fd[1]);  // Important (in general)
        execvp(myargv2[0], myargv2);
        perror(myargv2[0]);
        exit(4);
    }

    return 0;
}

一个简单的经验法则是:

  • 如果您将管道的一端dup()dup2() 连接到标准输入或标准输出,则应关闭这两个原始管道文件描述符。

给定输入文件 colorfile.txt 包含:

this is the color of danger
coloration is not important
end of file is.

程序的输出是:

HERE13
HERE1
this is the colour of danger
colouration is not important
end of file is.

有趣的是,如果程序的输出通过管道传输到另一个程序,则不会打印调试信息。这是默认缓冲的结果。

【讨论】:

    猜你喜欢
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 2020-08-27
    • 2021-05-07
    相关资源
    最近更新 更多