使用管道的sed命令会导致无限循环

时间:2014-03-07 00:29:48

标签: c sed exec pipe dup

所以我试图使用管道来捕获一个文件并将其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;
}

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

谢谢!

1 个答案:

答案 0 :(得分:0)

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

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.

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