2

我正在阅读 glibc 代码,特别是 login_tty 函数,我发现了一段对我来说没有多大意义的代码:

newfd = open (fdname, O_RDWR);
(void) close (newfd);

这会打开一个文件并立即关闭它,我想知道为什么

完整的功能代码

int
login_tty (int fd)
{
        (void) setsid();
#ifdef TIOCSCTTY
        if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1)
                return (-1);
#else
        {
          /* This might work.  */
          char *fdname = ttyname (fd);
          int newfd;
          if (fdname)
            {
              if (fd != 0)
                (void) close (0);
              if (fd != 1)
                (void) close (1);
              if (fd != 2)
                (void) close (2);
              newfd = open (fdname, O_RDWR);
              (void) close (newfd);
            }
        }
#endif
        while (dup2(fd, 0) == -1 && errno == EBUSY)
          ;
        while (dup2(fd, 1) == -1 && errno == EBUSY)
          ;
        while (dup2(fd, 2) == -1 && errno == EBUSY)
          ;
        if (fd > 2)
                (void) close(fd);
        return (0);
}
4

2 回答 2

3

我无法给出明确的答案,但它以某种方式试图使终端与进程fd控制终端相关联。

如果您查看代码的第一个替代方案,它使用ioctl: TIOCSCTTY。这被记录为“使给定终端成为调用进程的控制终端。[...] ”,例如参见此手册页

您不理解的代码在TIOCSCTTYioctl 不可用时使用的替代部分。我只能猜测,在关闭所有标准文件描述符(0to 2)之后,打开一个 tty 文件可能会产生副作用,使其成为控制终端。

于 2018-07-30T12:14:20.247 回答
1

根据APUE(2005 年第 2 版)第 9.6 节 - 控制终端:

POSIX.1 将用于分配控制终端的机制的选择留给每个单独的实现。我们将在 19.4 节中展示实际的步骤。

当会话领导者打开尚未与会话关联的第一个终端设备时,源自 UNIX System V的系统会为会话分配控制终端。这假设open会话领导者的调用没有指定O_NOCTTY标志(第 3.3 节)。

当会话领导者使用请求参数(第三个参数是空指针)调用 时,ioctlTIOCSCTTY基于 BSD 的系统为会话分配控制终端。会话不能已经有一个控制终端以使此调用成功。(通常,这个调用ioctl跟在对 的调用setsid之后,它保证进程是一个没有控制终端的会话领导者。)O_NOCTTY基于 BSD 的系统不使用 POSIX.1 标志打开,除非在兼容模式支持其他系统。

于 2018-07-30T15:55:24.723 回答