c - stdin 在 Linux 中是否被视为字符设备?

标签 c linux io operating-system input-devices

当我说标准输入时,我指的是 fd = 0 所指的

我正在学习一个涵盖 block 和字符设备的操作系统类(class)。它专门说键盘是一个字符设备。然而,当我们看到 read 系统调用时,我们被告知内核不关心它正在读取什么,只要它是 block 设备或 block 设备上的文件即可。

这是我们得到的代码:

#include <stdlib.h>
#include <unistd.h>

const int BUFFSIZE = 5;

int main () {
  int fd, n;
  char buffer[BUFFSIZE];

  int stdin = 0;
  int stdout = 1;
  int stderr = 2;

  do {
    n = read (0, buffer, BUFFSIZE);
    if (n < 0) {
      write (stderr, "Error occurred\n", 10);
    } else {
      write (stdout, "Entered if\n", 20);
      write (stdout, buffer, n);
    }
  } while (n > 0);
  return 0;
}

我的问题是:Linux 如何处理标准输入 (fd = 0)?它是否被视为字符设备,或者内核是否做了某种缓冲(从我运行代码时得到的结果来看,这似乎很可能。)

此外,了解我是否可以使用 read 系统调用来读取一般的字符设备会很有用。如果是,输入是否缓冲?

最佳答案

内核通常很少或根本不对字符设备进行缓冲。

内核在读取文件系统中的文件时会进行一定量的缓冲。

你不能说什么是设备标准输入,因为它因进程而异。默认情况下,fd 0 通常是用户的键盘,它是一个字符设备。但是如果我说

program < file

那么fd 0就是一个普通文件。如果我说

program < /dev/hda0

那么fd 0就是一个 block 设备。如果我努力的话,我也可能设法让 fd 0 连接到网络套接字。

在 Linux 中,还有 /proc/<em>pid</em>/fd/0 ,但这也不是设备;它最终看起来像是指向实际设备的符号链接(symbolic link) /dev ,无论它是什么。


附录:特定设备是否被缓冲实际上取决于该设备的驱动程序是如何编写的。任何给定的驱动程序可能会或可能不会实现某种形式的缓冲。此外,缓冲是否实际使用可能最终取决于其他因素。 (例如,Unix 终端驱动程序默认都是行缓冲的,但如果您将驱动程序置于“cbreak”或“raw”模式,则该缓冲将关闭)。我不认为你可以做出任何一般性的陈述来说明字符或 block 设备是否被缓冲。


附录 2:当您开始层层剥离时,它会变得相当复杂。 Unix 努力(通常做得很好)在按我的意思去做和保持简单、愚蠢之间取得适当的平衡。例如,如果您有一个行缓冲的终端,并且您要求输入 10 个字符,但只有 3 个可用,read()将返回 3。这是正确的,但它表明某处仍有一个缓冲区,这三个字符在键入时间和阅读时间之间累积。此外,如果您只要求 3 个,但有 10 个可用,在某些情况下,我认为其他 7 个会为您保留,这再次表明相当多的内核级缓冲。

但是在原始模式下,我很确定如果您阅读的速度不够快,您可能会丢失字符。将我们的注意力从终端驱动程序转移到网络套接字上,我认为在某些情况下,如果您执行 read()在 UDP 模式套接字上,实际的 UDP 数据包比您的读取请求大,您也可能在那里丢失其余的数据包。 [尽管评论者认为我可能是错的。](另一方面,TCP 模式套接字显然有大量缓冲!)

因此,归根结底:规则可能很复杂,准确的细节肯定不仅取决于所使用的特定设备驱动程序,还可能取决于无数其他细节。

关于c - stdin 在 Linux 中是否被视为字符设备?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36559689/

相关文章:

c++ - C++中的桶指针是什么?

c - 同一个文件描述符 fd 上的多个 fdopen()?

php - 无法登录 phpmyadmin 并且没有显示错误

linux - 我需要将旧驱动器添加到新的 Linux 安装中

c++ - 使用 socketpair 时 SO_SNDBUF 的行为

c - 在没有 CUDA 的情况下检测 NVIDIA GPU

自动执行时 C# Mono 程序在树莓派上崩溃

java - getClassLoader().getResource() 抛出 NullPointerException?为什么不是 FileNotFoundException?

Java I/O : How to append to an already existing text file

c# - 将二进制文件读入结构