【发布时间】:2015-12-10 19:48:51
【问题描述】:
我正在尝试在为类 Unix 操作系统 (xV6) 编写的 shell 中实现 I/O 重定向。在我正在阅读的操作系统手册中,我发现以下代码将在 shell 中运行以执行 cat 命令:
char *argv[2];
argv[0] = "cat";
argv[1] = 0;
if(fork() == 0) {
close(0);
open("input.txt", O_RDONLY);
exec("cat", argv);
}
我修改了代码以在我的 shell 中运行,该 shell 的 argv 数组位于另一个函数中,但它保留了该功能。出于某种原因,当我运行 cat < input.txt 时,shell 输出:
cat: -: Bad file descriptor
cat: closing standard input: Bad file descriptor
我还是操作系统编程的新手,所以我并不完全清楚 I/O 重定向的所有功能,但我认为我拥有的代码应该可以工作。什么可能导致问题。我有下面的 I/O 重定向代码:
case '<':
ecmd = (struct execcmd*)cmd;
rcmd = (struct redircmd*)cmd;
if(fork() == 0){
close(0);
open("input", O_RDONLY);
execvp(ecmd->argv[0], ecmd->argv );
}
runcmd(rcmd->cmd);
break;
编辑
我做了strace -e open ls 并得到:
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libacl.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libpcre.so.3", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/proc/filesystems", O_RDONLY) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
a.out sh.c test
+++ exited with 0 +++
编辑 2
出于某种原因,此案例的代码有效,但我不确定为什么:
case '<':
rcmd = (struct redircmd*)cmd;
close(rcmd->fd);
if(open(rcmd->file, rcmd->mode) < 0){
printf(2, "Cannot open file %s\n", rcmd->file);
perror(rcmd->file);
exit(1);
}
runcmd(rcmd->cmd);
break;
【问题讨论】:
-
你能打印出
open()在你的代码中返回的值吗? -
@MarkPlotnick 如何检查 open() 返回的内容?在 shell 中,它只输出错误的描述符消息。
-
您也可以尝试在
strace下运行您的程序,以跟踪它发出的所有系统调用:strace -f -o /some/output/file/name program [args]。见linux.die.net/man/1/strace -
您可以将
open的结果分配给一个变量,并使用printf打印该变量的值。在您的书中查找fork示例,了解如何进行变量赋值和对printf的调用。 -
书中的代码实现了一个非常具体的I/O重定向实例:从一个名为
input.txt的文件中读取。如果该文件不存在,open将返回特殊值-1,它不是有效的文件描述符,用于指示错误。第二个代码 sn -p 更好;它似乎使用用户提供的文件名,并检查从open返回的值。
标签: c linux operating-system xv6