libc函数isatty()如何工作?

时间:2019-06-02 22:18:53

标签: c unix libc

我搜索了Linux存储库,但找不到它的定义,所以我想它是C或类似的东西?我试图了解... | if type=="string" then [.] else . end | .[] | ... 如何能够用技术语言判断文件描述符是否为终端,以及“成为终端”的含义。

我不太确定在哪里可以找到它的实现,而且如果它在组装中,我将很难真正地跟随它。

2 个答案:

答案 0 :(得分:1)

实现isatty的一般策略是尝试对文件描述符进行特定于tty的ioctl操作,并检查ENOTTY错误结果。传统上,使用TCGETS,它是tcgetattr函数的后端,但是这有点危险,因为Linux上的ioctl数字与传统的OSS声音设备冲突,如果文件描述符实际上是指某种类型的MIDI设备,它将对设备进行更改。在musl libc中,我们使用TIOCGWINSZ(“获取窗口大小”操作),该数字不会无意间被其他类型的设备重用,对于非tty设备,其可靠地以ENOTTY失败。

理论上,您可以使用fstat进行操作,并检查st_rdev字段中的设备专业编号,但这将需要所有设备专业的ttys的硬编码列表,并且会添加新类型(例如USB串行/ ACM设备,uartlite设备等)时,打印机已损坏。

答案 1 :(得分:1)

isatty(3)是一个库函数(在Linux内核中找不到任何内容),通常是通过调用tcgetattr(3)并检查其返回值来实现的。

例如,在GNU C library(glibc)中:

/* Return 1 if FD is a terminal, 0 if not.  */
int
__isatty (int fd)
{
  struct termios term;

  return __tcgetattr (fd, &term) == 0;
}

tcgetattr(3)本身将解析为诸如TCGETATCGETS之类的ioctl。

请注意,isatty(3)对于伪tty的主端也将返回true,而这并不是真正的tty,对其执行的大多数tty相关操作实际上将应用于其从属端。

在Linux上,isatty(3)也将为/dev/console返回true,这又不是真正的tty(不能将其作为进程的控制tty)。

在linux上,您可以通过cat /proc/tty/drivers获得系统上所有tty驱动程序的列表,包括其主要编号和次要编号。当然,这仅反映了已加载的模块。