管道重定向问题,丢失数据
pipe redirection issue, lost data
我想用一个小的 c 程序重现这个 shell 行为:
< file cmd1 | cmd2
所以它需要三个参数,可以这样执行,例如:
./a.out foo /bin/cat /usr/bin/wc
这是我的代码,没有错误检查:
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
static void exe_cmd(char *cmd, char **env)
{
int pid;
char *av[] = {cmd, NULL};
pid = fork();
if (pid == 0)
{
execve(av[0], av, env);
exit(0);
}
waitpid(pid, NULL, 0);
}
static void left_pipe_side(int fd[2], char *cmd, char *path, char **env)
{
int file;
file = open(path, O_RDONLY);
dup2(fd[1], STDOUT_FILENO); // Can be commented out to see the first command output
dup2(file, STDIN_FILENO);
close(fd[0]);
close(fd[1]);
close(file);
exe_cmd(cmd, env);
}
static void right_pipe_side(int fd[2], char *cmd, char **env)
{
dup2(fd[0], STDIN_FILENO);
close(fd[1]);
close(fd[0]);
exe_cmd(cmd, env);
}
int main(int ac, char **av, char **env)
{
int fd[2];
pid_t pid;
pid = fork();
pipe(fd);
if (pid == 0)
{
left_pipe_side(fd, av[2], av[1], env);
exit(0);
}
right_pipe_side(fd, av[3], env);
waitpid(pid, NULL, 0);
return (0);
}
我的问题是 wc
作为第二个命令的输出将始终是 0 0 0
,就好像输入是空的(但给定的文件包含文本)。
如果我在左侧管道中注释掉我将 fd[1] 复制到 stdout 的行,第一个命令将正确输出,所以我不明白为什么重定向使这些数据“消失”
您在 fork
之后打开 pipe
,因此每个进程都有自己的非常 无关 pipe
。之前打开它,以便它在进程之间共享。
pipe(fd);
pid = fork();
在您的代码中,您在 fork
之后打开 pipe
,这意味着每个进程都有自己的 pipe
而这不是管道的工作方式
您必须在 fork
之前打开 pipes
,这将使进程与您的管道链接。
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
static void exe_cmd(char *cmd, char **env)
{
int pid;
char *av[] = {cmd, NULL};
pid = fork();
if (pid == 0)
{
execve(av[0], av, env);
exit(0);
}
waitpid(pid, NULL, 0);
}
static void left_pipe_side(int fd[2], char *cmd, char *path, char **env)
{
int file;
file = open(path, O_RDONLY);
dup2(fd[1], STDOUT_FILENO); // Can be commented out to see the first command output
dup2(file, STDIN_FILENO);
close(fd[0]);
close(fd[1]);
close(file);
exe_cmd(cmd, env);
}
static void right_pipe_side(int fd[2], char *cmd, char **env)
{
dup2(fd[0], STDIN_FILENO);
close(fd[1]);
close(fd[0]);
exe_cmd(cmd, env);
}
int main(int ac, char **av, char **env)
{
int fd[2];
pid_t pid;
/************************ the error part **********************/
// pid = fork();
// pipe(fd);
pipe(fd);
pid = fork();
/**************************************************************/
if (pid == 0)
{
left_pipe_side(fd, av[2], av[1], env);
exit(0);
}
right_pipe_side(fd, av[3], env);
waitpid(pid, NULL, 0);
return (0);
}
我想用一个小的 c 程序重现这个 shell 行为:
< file cmd1 | cmd2
所以它需要三个参数,可以这样执行,例如:
./a.out foo /bin/cat /usr/bin/wc
这是我的代码,没有错误检查:
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
static void exe_cmd(char *cmd, char **env)
{
int pid;
char *av[] = {cmd, NULL};
pid = fork();
if (pid == 0)
{
execve(av[0], av, env);
exit(0);
}
waitpid(pid, NULL, 0);
}
static void left_pipe_side(int fd[2], char *cmd, char *path, char **env)
{
int file;
file = open(path, O_RDONLY);
dup2(fd[1], STDOUT_FILENO); // Can be commented out to see the first command output
dup2(file, STDIN_FILENO);
close(fd[0]);
close(fd[1]);
close(file);
exe_cmd(cmd, env);
}
static void right_pipe_side(int fd[2], char *cmd, char **env)
{
dup2(fd[0], STDIN_FILENO);
close(fd[1]);
close(fd[0]);
exe_cmd(cmd, env);
}
int main(int ac, char **av, char **env)
{
int fd[2];
pid_t pid;
pid = fork();
pipe(fd);
if (pid == 0)
{
left_pipe_side(fd, av[2], av[1], env);
exit(0);
}
right_pipe_side(fd, av[3], env);
waitpid(pid, NULL, 0);
return (0);
}
我的问题是 wc
作为第二个命令的输出将始终是 0 0 0
,就好像输入是空的(但给定的文件包含文本)。
如果我在左侧管道中注释掉我将 fd[1] 复制到 stdout 的行,第一个命令将正确输出,所以我不明白为什么重定向使这些数据“消失”
您在 fork
之后打开 pipe
,因此每个进程都有自己的非常 无关 pipe
。之前打开它,以便它在进程之间共享。
pipe(fd);
pid = fork();
在您的代码中,您在 fork
之后打开 pipe
,这意味着每个进程都有自己的 pipe
而这不是管道的工作方式
您必须在 fork
之前打开 pipes
,这将使进程与您的管道链接。
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
static void exe_cmd(char *cmd, char **env)
{
int pid;
char *av[] = {cmd, NULL};
pid = fork();
if (pid == 0)
{
execve(av[0], av, env);
exit(0);
}
waitpid(pid, NULL, 0);
}
static void left_pipe_side(int fd[2], char *cmd, char *path, char **env)
{
int file;
file = open(path, O_RDONLY);
dup2(fd[1], STDOUT_FILENO); // Can be commented out to see the first command output
dup2(file, STDIN_FILENO);
close(fd[0]);
close(fd[1]);
close(file);
exe_cmd(cmd, env);
}
static void right_pipe_side(int fd[2], char *cmd, char **env)
{
dup2(fd[0], STDIN_FILENO);
close(fd[1]);
close(fd[0]);
exe_cmd(cmd, env);
}
int main(int ac, char **av, char **env)
{
int fd[2];
pid_t pid;
/************************ the error part **********************/
// pid = fork();
// pipe(fd);
pipe(fd);
pid = fork();
/**************************************************************/
if (pid == 0)
{
left_pipe_side(fd, av[2], av[1], env);
exit(0);
}
right_pipe_side(fd, av[3], env);
waitpid(pid, NULL, 0);
return (0);
}