使用 fork() 和 pipe() 时将标准输入输入 execvp()
stdin into execvp() while using fork() and pipe()
所以我尝试从标准输入中读取,然后准备好输入,以便稍后可以在 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);
}
}
一个主要问题是您在 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;
}
当我运行程序时,它会产生适当的输出。请注意 main()
末尾的 return
实际上从未达到。
所以我尝试从标准输入中读取,然后准备好输入,以便稍后可以在 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);
}
}
一个主要问题是您在 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;
}
当我运行程序时,它会产生适当的输出。请注意 main()
末尾的 return
实际上从未达到。