作者热门文章
- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试在 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));
}
}
}
我做了以下更改:
关于c - Linux 上带有管道和 I/O 重定向的 Shell 模拟器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36113746/
我是一名优秀的程序员,十分优秀!