gpt4 book ai didi

c - Linux 上带有管道和 I/O 重定向的 Shell 模拟器

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:25:19 25 4
gpt4 key购买 nike

我正在尝试在 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 中的函数。首先我复制 STDIO 用于 I/O 重定向后的恢复。然后我将我的文件描述符复制到 STD_IN 和 STD_OUT。然后我执行管道,最后我恢复我的 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);
}

最佳答案

我在你自己的仓库上推送了两个提交,它们包含你需要的修复

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));
}
}
}

我做了以下更改:

  1. 现在两个 child 都是从同一个顶级 parent 创建的
  2. 现在顶层父关闭他的管道文件描述符副本
  3. 现在顶层 parent 正确地等待它的 child
  4. 添加了急需的状态检查

关于c - Linux 上带有管道和 I/O 重定向的 Shell 模拟器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36113746/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com