繁体   English   中英

使用 fork() 和 pipe() 时标准输入到 execvp()

[英]stdin into execvp() while using fork() and pipe()

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

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

这是我的代码示例的运行方式。

输入:

ls -s1

排序 -n

output:

命令[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);
    }
}

一个主要问题是您在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 > 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;
}

当我运行程序时,它会生成适当的 output。 请注意,实际上从未达到main()末尾的return

暂无
暂无

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

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