我刚刚完成了我的 shell 解释器,但我认为我的管道实现是错误的。
它正在工作,像ls | cat -e工作这样的基本东西,但segmentation fault如果文件描述符超过 60 ko,我害怕可能性。当我做一个超过 60 ko 的文件的 cat 时,我也发现了一个无限循环。例如,如果 do a cat foo | cat -efoo 是一个长文件,则会发生无限循环。
或其他示例,当我执行cat /dev/urandom | cat -e此操作时不会向我显示任何显示,因此它首先执行cat /dev/urandom,然后执行cat -e.
这是我的代码:
int son(int *fd_in, int p[2], t_list *cmd, char **env)
{
(void)env;
dup2(*fd_in, 0);
if (cmd->act != ENDACT && cmd->act != LEFT && cmd->act != DLEFT)
dup2(p[1], 1);
close(p[0]);
execve(cmd->av[0], cmd->av, NULL);
return (-1);
}
t_list *execute_pipe(t_list *cmd, int *fd_in)
{
int p[2];
pid_t pid;
*fd_in = 0;
while (cmd->act != -1)
{
pipe(p);
if ((pid = fork()) == -1)
return (NULL);
else if (pid == 0)
son(fd_in, p, cmd, NULL);
else
{
wait(NULL);
close(p[1]);
*fd_in = p[0];
if (cmd->act != PIPE)
return (cmd);
cmd = cmd->next;
}
}
return (cmd);
}
Run Code Online (Sandbox Code Playgroud)
shell 管道的部分想法是所涉及的进程并发运行(或可能会运行)。您提供的代码通过wait()在启动下一个子进程之前对每个子进程进行 ing 来主动防止这种情况发生。除其他事项外,这会冒着在准备好耗尽它之前填充(操作系统级)管道缓冲区的风险。这将陷入僵局,或者,如果幸运的话,会产生错误。
在较高级别,该过程应如下所示:
C最初是管道第一段的命令,并设置fd0为STDIN_FILENOpipe(),并设置fd1为该管道的写端;fd1为STDOUT_FILENOfork()在其中运行 command 的子项C。在里面:
fd0与STDIN_FILENOthen不同dup2() fd0on STDIN_FILENOand closefd0fd1与STDOUT_FILENOthen不同dup2() fd1on STDOUT_FILENOand closefd1Cfd0不同于STDIN_FILENO则关闭fd0fd1不同于STDOUT_FILENO则关闭fd1C为下一个命令fd0为上面步骤(2)中管道的读取端wait()或waitpid()所有子进程请注意,对于包含任意正数命令(包括 1)的管道,这同样适用。
| 归档时间: |
|
| 查看次数: |
2763 次 |
| 最近记录: |