在shell中运行cat命令时文件描述符错误

时间:2015-09-14 18:04:03

标签: c linux operating-system xv6

我试图在我为类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中运行,其中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 +++

编辑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;

1 个答案:

答案 0 :(得分:4)

您不能只关闭stdin然后打开另一个文件。它不会自动成为您的新标准输入。你想要的是使用syscall dup2,它可以将文件描述符“重定向”到另一个。

RotateAnimation rotate = new RotateAnimation(fromDegrees, toDegrees, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    rotate.setDuration(400);
    rotate.setFillEnabled(true);
    rotate.setFillAfter(true);
    rotate.setInterpolator(new LinearInterpolator());
    rotate.setAnimationListener(new Animation.AnimationListener() {
    });
    photo.startAnimation(rotate);

有关详细信息,请参阅man 2 dup2。请注意,open和dup2都可能都失败,所以如果这是一个问题,你应该检查它们的返回值。

编辑:这实际上会有效,因为POSIX保证内核将始终分配最低的空闲文件描述符。但它不是线程安全的,而且通常只是糟糕的风格。我建议总是做dup2,即使在某些情况下你可以在没有它的情况下离开。