C语言 在xv6中实现dup2

6yoyoihd  于 2022-12-11  发布在  其他
关注(0)|答案(1)|浏览(214)

我正在学习一门操作系统课程,我们必须在xv 6中实现dup2()。我编写的代码理论上应该可以工作,但是,当我尝试执行测试时,它并没有通过所有测试。
这是我的系统调用:

int sys_dup2(void) {
  int oldfd, newfd;
  struct file *oldf, *newf;  

  struct proc *curproc = myproc();

  if (argfd(0, &oldfd, &oldf) < 0)
    return -1;
  if (argfd(1, &newfd, &newf) < 0)
    return -1;

  if (oldfd == newfd)
    return newfd;
  if (newfd != 0)
    fileclose(newf);

  filedup(oldf);
  curproc->ofile[newfd] = oldf;
  return newfd;
}

未通过的测试包括:

if (dup2 (1,4) != 4)
  printf (2, "dup2 not working with existing fd.\n");

printf (4, "This message outputs on terminal.\n");

if (dup2 (4,6) != 6)
  printf (2, "dup2 not working with existing fd (2).\n");

我认为这个问题与argfd()有关,因为当我尝试用GDB调试时,我发现oldfd等于某个随机数。
这是xv 6的argfd()

static int
argfd(int n, int *pfd, struct file **pf)
{
  int fd;
  struct file *f;

  if(argint(n, &fd) < 0)
    return -1;
  if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
    return -1;
  if(pfd)
    *pfd = fd;
  if(pf)
    *pf = f;
  return 0;
}

我留下xv 6的函数argint()fetchint()filedup(),以便更好地理解上面的代码。
第一个
感谢您的帮助!

06odsfpq

06odsfpq1#

无论newfd是否打开,dup2(oldfd, newfd)都应该工作。在我看来,如果使用未打开的文件描述符调用argfdargfd将失败(假定myproc()->ofile表中的相应条目为空),在这种情况下,您的函数只返回-1,这是错误的。所以你不能用argfd来验证newfd参数。也许有其他的标准函数可用,或者你只需要自己做同样的检查。
测试中并不清楚fd 4是否应该已经打开(“现有fd”是指旧的还是新的?),但如果不是,那么看起来您的实现确实会失败。
测试if (newfd != 0)看起来也是错误的; 0是一个有效的文件描述符(标准输入),所以不应该区别对待。事实上,每次在shell中使用<输入重定向时,都需要使用dup2(fd, 0)。我不确定您在这里输入什么,但当您重新进行验证时,它可能无论如何都要更改。
最后,我不知道xv 6的并发和线程规则是什么,但我担心竞争和TOCTOU错误。在检查文件描述符的有效性/状态和执行实际工作之间,您没有任何锁。
如果这个进程的另一个线程在您测试oldfdnewd后关闭它,并释放struct file,那么您的struct file *就是悬空的。
dup2操作应该是原子的,因此另一个线程中的write(newfd, data, sz)应该写入原始的newfd或复制的oldfd,但不应该在EBADF时失败。如果写操作发生在fileclose(newf)curproc->ofile[newfd] = oldf;之间的窗口中,则代码中会出现这种情况。

相关问题