您能给我一些有关以下代码的想法吗?该代码运行,但不会退出。另一个字符串s="ls -1"
效果很好。通过sh(1)
运行shell片段也可以。
#include <unistd.h>
#include <string.h>
int
main(int argc, char *argv[])
{
int fd[2];
char *s = "ls -1 \"/usr/bin\" | while IFS= read -r fp\ndo\ncat <<- EOF\n\t$fp\nEOF\ndone;";
//char *s = "ls -1";
pipe(fd);
switch(fork()) {
case 0:
close(fd[1]);
dup2(fd[0], 0);
execl("/bin/sh", "sh", NULL);
close(fd[0]);
break;
default:
close(fd[0]);
write(fd[1], s, strlen(s) + 1);
close(fd[1]);
break;
}
return 0;
}
答案 0 :(得分:3)
当我将评论转换为答案时,我测试了建议的更改,但并没有解决问题。一种有效的解决方法是在字符串的末尾添加; exit
,即使这等同于作弊。但是,测试还表明它没有完成。好像ls
没有终止。
我去了另一个终端,以查看ls
或pipe97
(您的代码的名字)的处理是否仍然存在;他们不是。
ps
。您应该获得正常的输出和提示。
由于父级不等待子级退出,因此提示在ls
的输出中丢失了一个提示(该提示很长并且产生得很慢)。将输出重定向到/dev/null
,您将看到提示。
wait()
循环,这样它直到子进程之后才退出。#include <sys/wait.h>
…
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
;
在调试时,您可以打印corpse
和status
,以便了解发生了什么情况。
我发现这个comment(没有其序言)仍然有效:
…
close(fd[0]);
必须在execl()
之前—记住,如果成功,execl()
永不返回(仅在失败时返回)。可以说,您应该在exit(1);
之后有一个错误报告和execl()
或类似内容;此刻,您即使失败也报告成功。
Rule of Thumb注释本身是有效的,但实际上不适用于此代码-未关闭的管道描述符不会引起麻烦,即使没有关闭本应关闭的管道描述符也是如此。
答案 1 :(得分:1)
@WilliamPursell谢谢,您是对的。在这个示例中,我并没有专注于此。
@ user3629249我知道我没有进行正确的错误检查,谢谢!
@mosvy是OpenBSD,实际上是在Mac上运行的。
此版本有效:
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int
main(int argc, char *argv[])
{
int fd[2];
char *s = "ls -1 '/usr/bin' | while IFS= read -r fp\ndo\ncat <<- EOF\n\t$fp\nEOF\ndone;";
//char *s = "ls -1";
pipe(fd);
switch(fork()) {
case 0:
close(fd[1]);
dup2(fd[0], 0);
execl("/bin/sh", "sh", NULL);
close(fd[0]);
break;
default:
close(fd[0]);
write(fd[1], s, strlen(s));
close(fd[1]);
wait(NULL);
break;
}
return 0;
}
是wait(2)
做到了。我记得我曾经做过wait(2)
,但是我想我把close(1)
的顺序弄错了,所以它阻塞了。
无论如何,问题已解决,谢谢!