[英]Bad file descriptor when running cat command in a shell
我正在嘗試在要為類似Unix的OS(xV6)編寫的外殼中實現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);
}
我修改了代碼以使其在具有argv數組的外殼程序中運行,該外殼程序位於另一個函數中,但它保留了該功能。 由於某些原因,當我運行cat < input.txt
,shell輸出:
cat: -: Bad file descriptor
cat: closing standard input: Bad file descriptor
我仍然是OS編程的新手,所以我對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 +++
由於某種原因,這種情況下的代碼有效,但是我不確定為什么:
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;
您不能只關閉stdin然后打開另一個文件。 它不會自動成為您的新標准輸入。 您要使用的是syscall dup2,它可以將文件描述符“重定向”到另一個文件描述符。
int fd = open("input.txt", O_RDONLY);
dup2(fd, 0); // stdin now points to fd
close(fd);
有關更多信息,請參見man 2 dup2 。 請注意,open和dup2都可能失敗,因此,如果您對此感到擔憂,則應檢查它們的返回值。
編輯 :這有時實際上會工作,因為POSIX保證內核將始終分配最低的空閑文件描述符。 但是它不是線程安全的,並且通常只是不好的樣式。 我建議始終執行dup2,即使在某些情況下,如果沒有它,您可能會逃脫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.