0

所以我正在尝试使用管道来 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;
}

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

谢谢!

4

1 回答 1

0

一个主要问题是您无法决定是使用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.

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

于 2014-12-15T08:18:02.837 回答