我正在尝试在Linux上编写一个shell模拟器,它可以执行单进程命令,双进程管道和I / O重定向。 然而,当我正确地执行以下单个过程时,管道存在一些问题。
Copy_STDIO(); //Copy the stdio for the restoration.
Redirection(); //Determine whether should do Redirection.
Pipeline();
Restore_stdio(); //Restore the stdio.
以上是我在main中的功能。首先,我在I / O重定向后复制STDIO以进行恢复。然后我将我的文件描述符复制到STD_IN和STD_OUT。然后我执行Pipeline,最后我恢复了STD_IN和STD_OUT。一切听起来都很完美,但事实并非如此。我的OUTPUT重定向失败,这意味着它没有向目标文件写入任何内容(即,如果在单一情况下:ls> 123,123没有显示任何内容),当我的程序仍在运行时。但是当我用exit(EXIT_SUCCESS)终止程序时,它出现!!(如果用ctrl + c,它也失败了),我不知道为什么!
void Redirection()
{
fd_out = open(filename[0],O_WRONLY | O_TRUNC | O_CREAT,S_IRWXU | S_IRWXG | S_IRWXO); //O_WRONLY and O_CREAT must use at the same time.
dup2(fd_out,STD_OUTPUT);
close(fd_out);
}
void Copy_STDIO()
{
STDIN_COPY = dup(STD_INPUT); //Copy for the stdin and stdout
STDOUT_COPY = dup(STD_OUTPUT);
}
void Pipeline()
{
if(pipeline)
{
pipe(&fd[0]);
childID=fork();
if(childID==0)
{
if(fork()!=0)
{
close(fd[1]);
dup2(fd[0],STD_INPUT);
close(fd[0]);
execvp(args2[0],args2);
}
else
{
close(fd[0]);
dup2(fd[1],STD_OUTPUT);
close(fd[1]);
execvp(args[0],args);
}
}
usleep(5000);
}
}
void Restore_stdio()
{
dup2(STDIN_COPY,STD_INPUT); //Restore the output and input to the stdin and stdout.
dup2(STDOUT_COPY,STD_OUTPUT);
close(STDIN_COPY);
close(STDOUT_COPY);
}
答案 0 :(得分:0)
我在您自己的存储库中推送了两个提交,它们包含您需要的修补程序
void Pipelining()
{
int otherID = 0;
childID = 0;
int childs = 0;
int ret = 0;
if(pipeline)
{
pipe(fd);
childID=fork();
if (childID < 0) {
fprintf(stderr, "error: 1 ... %s\n", strerror(errno));
return;
} else if (childID > 0) {
++childs;
otherID = fork();
if (otherID < 0) {
fprintf(stderr, "error: 2 ... %s\n", strerror(errno));
ret = waitpid(childID, NULL, 0);
if (ret < 0) {
fprintf(stderr, "error: 3 ... %s\n", strerror(errno));
}
return;
} else if (otherID > 0) {
++childs;
} else {
close(fd[0]);
ret = dup2(fd[1],STD_OUTPUT);
if (ret < 0) {
fprintf(stderr, "error: 4 ... %s\n", strerror(errno));
}
close(fd[1]);
ret = execvp(args[0], args);
if (ret < 0) {
fprintf(stderr, "error: 5 ... %s\n", strerror(errno));
}
}
} else {
close(fd[1]);
ret = dup2(fd[0],STD_INPUT);
if (ret < 0) {
fprintf(stderr, "error: 6 ... %s\n", strerror(errno));
}
close(fd[0]);
ret = execvp(args2[0],args2);
if (ret < 0) {
fprintf(stderr, "error: 7 ... %s\n", strerror(errno));
}
}
/* now it is safe to close pipe */
close(fd[0]);
close(fd[1]);
/* wait children */
ret = waitpid(childID, NULL, 0);
if (ret < 0) {
if (errno != ECHILD)
fprintf(stderr, "error: 8 ... %s\n", strerror(errno));
}
ret = waitpid(otherID, NULL, 0);
if (ret < 0) {
if (errno != ECHILD)
fprintf(stderr, "error: 9 ... %s\n", strerror(errno));
}
}
}
我做了以下更改: