简体   繁体   English

Pipe execvp linux 从子进程到父进程的命令

[英]Pipe execvp linux command from child to parent process

I try to write a program in C language that takes a simple Linux command in input like "ls /home".我尝试用 C 语言编写一个程序,该程序在输入中采用简单的 Linux 命令,如“ls /home”。 This command is executed in child process with "execvp" and sent to the parent process to be displayed on the screen..该命令在带有“execvp”的子进程中执行,并发送到父进程以显示在屏幕上。

My problem is that the program is running and display nothing and don't give back the prompt.我的问题是程序正在运行但什么也不显示,也不返回提示。 I have to quit with "ctrl + C".我必须用“ctrl + C”退出。

Is the problem in the while loop or my pipe send my command nowhere?是 while 循环中的问题还是我的 pipe 无处发送我的命令?

Thanks for your feedback感谢您的反馈意见

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>

int main(int argc, char* argv[])
{
        int     fd[2];
        int   pid;

        pipe(fd);
        
        if((pid = fork()) == -1)
        {
                perror("fork");
                exit(1);
        }

        if(pid == 0)
        {
                close(fd[0]);

            dup2(fd[1], STDOUT_FILENO);

            close(fd[1]);

            execvp(argv[1], &argv[1]);
        }
        else
        {
                close(fd[1]);

            dup2(fd[0], STDIN_FILENO);
            close(fd[0]);
            char result;
            while(read(fd[0], &result, sizeof(result) > 0))
            {
                write(fd[1], &result, sizeof(result));
            }
            wait(NULL);
        }
    close(fd[1]); 
    close(fd[0]);
    return(0);
}

In the parent , the read loop has problems.parent中,读取循环有问题。 Compare相比

while(read(fd[0], &result, sizeof(result) > 0))

to

while(read(fd[0], &result, sizeof(result)) > 0)

The former, in your program, is using the result of the comparison sizeof(result) > 0 as the size of the buffer, and looping as long as read returns a nonzero value.前者在您的程序中使用比较sizeof(result) > 0的结果作为缓冲区的大小,并且只要read返回非零值就循环。

Note that result is a char , and sizeof (char) is guaranteed to be 1 .请注意, result是一个char ,并且sizeof (char)保证1

1 > 0 is 1 , which just happens to be the size of your buffer, so this partially works. 1 > 01 ,恰好是缓冲区的大小,所以这部分有效。 The loop will continue on error ( -1 ) though, and will continue to attempt writing output.尽管出现错误 ( -1 ),循环仍将继续,并将继续尝试写入 output。

It is also trying to read from fd[0] , which was closed after它还试图从fd[0]中读取,它在之后被关闭

dup2(fd[0], STDIN_FILENO);
close(fd[0]);

This duplication is not needed.不需要这种重复。

Additionally,此外,

write(fd[1], &result, sizeof(result));

is attempting to write the output back into the pipe. That said, the parent closed this file descriptor earlier ( close(fd[1]); ).正在尝试将 output 写回 pipe。也就是说,父级较早地关闭了此文件描述符( close(fd[1]); )。

Note the close(fd[1]);注意close(fd[1]); outside of the else block is redundant (and redundant closes can be a source of bugs in more complex programs). else块之外是多余的(多余的关闭可能是更复杂程序中错误的来源)。


In the child , you should handle the event that execvp fails, because if the function succeeds, it never returns.child中,您应该处理execvp失败的事件,因为如果 function 成功,它永远不会返回。 Anything expected to run after execvp is operating in a failure state (in your program, that is the lines after the else block).execvp运行失败预期运行的任何内容 state(在您的程序中,即 else 块之后的行)。


A cursory example:一个粗略的例子:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int fd[2];
    pid_t pid;

    if (argc < 2) {
        fprintf(stderr, "too few arguments\n");
        exit(EXIT_FAILURE);
    }

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

    if (-1 == (pid = fork())) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        /* child */
        close(fd[0]);
        dup2(fd[1], STDOUT_FILENO);
        close(fd[1]);

        argv++;

        execvp(*argv, argv);
        perror("execvp");
        exit(EXIT_FAILURE);
    }

    /* parent */
    char result;

    close(fd[1]);

    while (read(fd[0], &result, 1) > 0)
        write(STDOUT_FILENO, &result, 1);

    close(fd[0]);
    wait(NULL);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM