【问题标题】:stdin into execvp() while using fork() and pipe()使用 fork() 和 pipe() 时标准输入到 execvp()
【发布时间】:2021-07-23 10:06:36
【问题描述】:

所以我试图从标准输入中读取,然后准备好输入,以便稍后可以在 execvp() 中使用它。

我在这里实现的基本上是一些终端命令的管道。

这是我的代码示例。

输入:

ls -s1

排序-n

输出:

命令[0]="ls"

命令[1]="-s1"

commands2[0]="��""

commands2[1]="��""

排序:无法读取:t:没有这样的文件或目录

这是我的代码

# include <stdlib.h>
# include <stdio.h>
# include <unistd.h>
# include <string.h>
# include <sys/wait.h>
# define BUF_SIZE 256
    

int main()
{
    char buffer[BUF_SIZE];
    char *commands[5];
    char *commands2[5];
    int argc = 0;
    int argc2 = 0;

    fgets(buffer, BUF_SIZE, stdin);
        
        for ( commands[argc] = strtok(buffer, " \t\n"); 
              commands[argc] != NULL; 
              commands[++argc] = strtok(NULL, " \t\n") ) {
            printf("commands[%d]=\"%s\"\n", argc, commands[argc]);
        }
        commands[argc] = NULL;

    fgets(buffer, BUF_SIZE, stdin);
        
        for ( commands2[argc2] = strtok(buffer, " \t\n"); 
              commands2[argc2] != NULL; 
              commands2[++argc2] = strtok(NULL, " \t\n") ) {
            printf("commands2[%d]=\"%s\"\n", argc2, commands2[argc]);
        }
        commands2[argc2] = NULL;

    int my_pipe[2];

    if (pipe(my_pipe) == -1)
    {
        perror("cannot create pipe\n");
    }

    pid_t my_pid;

    my_pid = fork();

    if (my_pid < 0)
    {
        perror("Failed fork\n");
    }

    if (my_pid > 0)
    {
        close(my_pipe[1]);
        dup2(my_pipe[0], 0);
        close(my_pipe[0]);

        wait(NULL);
        execvp(commands2[0],commands2); 
    }
    else
    {
        close(my_pipe[0]);   
        dup2(my_pipe[1], 1);
        close(my_pipe[1]);

        execvp(commands[0],commands);
    }
}

【问题讨论】:

    标签: c stdin execvp


    【解决方案1】:

    一个主要的问题是你在buffer 的第一行上读取了第二行,而commands[] 数组也包含指向buffer 的指针。这不是幸福的秘诀。最简单的解决方法是定义char buffer2[BUF_SIZE]; 并在第二个fgets() 调用和for 循环中使用它。

    printf("commands2[%d]=\"%s\"\n", argc2, commands2[argc]); 中使用argc 是一个复制粘贴错误——它应该引用argc2 两次。这有助于隐藏之前的问题。

    注意perror() 不会退出;如果pipe() 失败,或者fork() 失败,您的代码就会出错。

    if (my_pid &gt; 0) 中的wait() 不好;删除它。

    如果execvp() 失败,您应该报告错误并以非零状态退出。

    将这些更改放在一起会产生如下代码:

    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/wait.h>
    
    #define BUF_SIZE 256
    
    int main(void)
    {
        char buffer[BUF_SIZE];
        char buffer2[BUF_SIZE];
        char *commands[5];
        char *commands2[5];
        int argc = 0;
        int argc2 = 0;
    
        fgets(buffer, BUF_SIZE, stdin);
    
        for (commands[argc] = strtok(buffer, " \t\n");
             commands[argc] != NULL;
             commands[++argc] = strtok(NULL, " \t\n"))
        {
            printf("commands[%d]=\"%s\"\n", argc, commands[argc]);
        }
        commands[argc] = NULL;
    
        fgets(buffer2, BUF_SIZE, stdin);
    
        for (commands2[argc2] = strtok(buffer2, " \t\n");
             commands2[argc2] != NULL;
             commands2[++argc2] = strtok(NULL, " \t\n"))
        {
            printf("commands2[%d]=\"%s\"\n", argc2, commands2[argc2]);
        }
        commands2[argc2] = NULL;
    
        int my_pipe[2];
    
        if (pipe(my_pipe) == -1)
        {
            perror("cannot create pipe\n");
            exit(EXIT_FAILURE);
        }
    
        pid_t my_pid = fork();
    
        if (my_pid < 0)
        {
            perror("Failed fork\n");
            exit(EXIT_FAILURE);
        }
    
        if (my_pid > 0)
        {
            close(my_pipe[1]);
            dup2(my_pipe[0], 0);
            close(my_pipe[0]);
    
            execvp(commands2[0], commands2);
            perror(commands2[0]);
            exit(EXIT_FAILURE);
        }
        else
        {
            close(my_pipe[0]);
            dup2(my_pipe[1], 1);
            close(my_pipe[1]);
    
            execvp(commands[0], commands);
            perror(commands[0]);
            exit(EXIT_FAILURE);
        }
        return EXIT_FAILURE;
    }
    

    当我运行程序时,它会产生适当的输出。请注意,main() 末尾的 return 实际上永远不会到达。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-17
      • 2014-03-27
      • 1970-01-01
      • 2018-08-30
      • 2013-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多