什么是 /dev/null,为什么我不能在它上面使用 hx?

Blu*_*awk 12 linux

我一直在查看 /dev,偶然发现了几个文件,包括null. 我想看看文件中有什么,所以我做了hx null,但什么也没发生,它给出了错误File null is not a regular file。是什么导致此消息?

xen*_*oid 67

中的几个对象/dev伪设备,由内核函数直接处理。比较常用的有:

  • /dev/null:无限容量的通用水槽。用于丢弃输出: try echo foo >/dev/null。从中读取会返回一个空的字节流(即刻 EOF)。
  • /dev/zero:无限的0x00字节来源。通常用作输入以用 0 覆盖事物。
  • /dev/random, /dev/urandom: 随机字节的无限来源。

  • 还有`/dev/full`,它在写入时返回`ENOSPC`,用于测试程序在磁盘空间不足时的行为方式 (49认同)
  • `/dev/random` 不连续:“当熵池为空时,从 /dev/random 读取将阻塞,直到收集到额外的环境噪声。” (`男人4随机`) (14认同)
  • 我说“最常用的那些”。有关完整列表,请参阅链接的维基百科或您友好的操作系统手册。 (8认同)
  • 还有用于对各种块层实现进行基准测试的空块设备 (/dev/nullb*) https://www.kernel.org/doc/Documentation/block/null_blk.txt (2认同)
  • @xenoid 这是错误的,参见 https://www.2uo.de/myths-about-urandom/ (2认同)

Rem*_*ica 25

事实上,其他答案似乎都没有真正回答为什么 hx 拒绝使用 /dev/null 的问题。hx 以这种方式作出反应的原因很简单,它被编程为为设备文件输出此错误消息。

来自https://github.com/krpors/hx/blob/develop/editor.c#L125

if (!S_ISREG(statbuf.st_mode)) {
        fprintf(stderr, "File '%s' is not a regular file\n", filename);
        exit(1);
Run Code Online (Sandbox Code Playgroud)

这意味着 hx 特别拒绝处理任何非常规文件。我不认为这个检查有很好的理由 - 没有它,我希望它/dev/null可以与 hx 一起使用,因为 hx 会读取一个空文件,并且在保存它们时对它的任何更新都会丢失。

(这里假设https://github.com/krpors/hx/确实是海报所说的 hx 程序)


Gri*_*fin 17

/dev/null 基本上是一种丢弃信息的方法。

主要目的只是为了能够将事物重定向到遗忘状态。

echo 'duck' > /dev/null
Run Code Online (Sandbox Code Playgroud)

将抑制由echo 'duck'发送到/dev/null并因此丢弃的消息。

这主要用于使用为您提供不想看到的输出的命令。

/dev/null立即读取返回文件结尾——即,它就像一个空文件。

还有其他/dev类似的有趣的东西random会给你随机数据;并不是您对“文件”的真正期望:) 值得注意的是,这/dev/random是从系统使用中收集的真正随机数据(击键之间的时间和类似的事情),并且该池可能会很快耗尽。/dev/urandom给你一个看似随机的数字,但却是由数学公式计算出来的。通常/dev/urandom可以满足您的需要,但例如非常强大的加密密钥还不够好。

您还可以从中读取/dev/zero以获取无限的零(空)字节流。

  • 这重复了一个关于`/dev/urandom`的[常见误解](https://unix.stackexchange.com/q/324209/91565)(它在某种程度上“不安全”或不够安全)。 (9认同)
  • @VL-80 正确,但当你引用那部分作为回复时,我的印象是你可能错过了我的观点,即澄清为回答而写的内容,因为普通用户可能认为从“文件”中读取数字意味着数字具有文本表示。 (2认同)

VL-*_*-80 11

我想在已经存在的答案中添加一个man null描述/dev/null/dev/zero文件的手册页。

姓名

null,零 - 数据接收器

描述

写入特殊文件的数据将被丢弃。

特殊文件读取总是返回文件结尾(即,read(2) 返回 0),而从读取总是返回包含零(\0 个字符)的字节。

nullzero通常由以下方式创建:

mknod -m 666 /dev/null c 1 3
mknod -m 666 /dev/zero c 1 5
chown root:root /dev/null /dev/zero
Run Code Online (Sandbox Code Playgroud)

文件

/开发/空
/开发/零

笔记

如果这些设备不是所有用户都可写和可读的,许多程序就会表现得很奇怪。

来源:https : //linux.die.net/man/4/null


xwi*_*ke- 8

/dev/null 是字符设备文件,即设备驱动程序的接口。

这个特定的设备是一个虚拟设备(不代表真正的硬件)。特制的无底垃圾桶;您可以将任何程序的输出转储到其中,以防您不希望它们显示或其他任何地方。

  • 内容方面,如果您确实尝试读取此文件(是的,您可以读取它),它将始终等同于一个空的 0 字节长度的文件

我不知道你的hx命令是什么,但我从你的描述中猜测它是一个通过内容识别文件类型的命令。我在 GNU/Linux 系统上用于此任务的命令是file,如果发现文件不是常规文件,它也会停止...

$ file /dev/null
/dev/null: character special
Run Code Online (Sandbox Code Playgroud)

但是file命令也提供了一个-s选项,它强制它无论如何读取......

$ file -s /dev/null
/dev/null: empty
Run Code Online (Sandbox Code Playgroud)

也许您的hx命令有类似的选项可供您使用?

之所以说file(也许你的hx命令太)默认情况下不识别非正规文件被暗示的文档-s选项file的手册页,即...

  • 阅读这些文件可能会导致副作用,有时是不受欢迎的副作用。
    • 从 FIFO 管道读取会永久消耗其中的数据,您无法将读取的数据推回到管道中。
    • 从设备文件读取导致设备更改...
      • 从磁带设备读取会导致磁头位置发生偏移。
      • 从串行端口设备读取会导致消耗缓冲的输入字节。
      • 从随机数设备读取会导致系统的熵池耗尽。
      • 还有更多,取决于相关设备的驱动程序。
  • 按内容识别这些特殊文件需要做更多的工作,但确定性要低得多:
    • 内容大小不会提前知道(或需要特殊的系统特定ioctl()调用才能获得)。
    • 寻求在很多情况下是行不通的。
    • 检测依赖于文件结尾签名的文件类型将需要通读整个内容。
    • 其中一些文件提供了无限的内容。

如果您的程序不是为处理所需的工作而设计的,那么它可能无法识别非常规文件的内容;并作为安全预防措施中止。

  • 如果程序在没有进行安全检查的情况下继续运行,可能会导致挂起崩溃,或者更糟的是,导致系统内存不足;取决于相关程序的设计。

如果是这种情况,则说明您的程序存在限制;用file -s以资识别来代替。


附录

如果您hx某种十六进制/二进制编辑器那么尤其不建议使用它来打开您不知道的特殊文件。十六进制编辑器通常会将整个文件预加载到内存中以进行编辑操作。

出于这个原因,如果你试图让它打开一个无限内容的设备文件(比如/dev/zero/dev/urandom)甚至一个大型的有限设备(比如/dev/sda),它可能会使你的系统进入内存不足的情况,你可能需要这样做重置整个机器以恢复。

您刚刚绊倒的安全检查可能会保护您免受这种情况的影响。(如前所述:设备文件的内容大小事先不知道——程序无法事先确定您是否有足够的内存来加载它)

万一你只想“偷看”文件的标题,无论如何;使用十六进制查看器,而不是hexdump(推荐),或老派od。例如:

  • hexdump -C -n 512 /dev/null (内容将为空)
  • hexdump -C -n 512 /dev/urandom (内容每次都会是不同的胡言乱语)

^ 该-n 512选项将视图限制为前 512 个字节。但即使你忽略了这一点,并被无休止的输出轰炸,你需要做的就是阻止它只是按下Ctrl+C


rex*_*ans 5

随着HX我想你的意思krpors的十六进制编辑器,可在Github上

在其源文件中editor.c,第 118 行 ff 说:

struct stat statbuf;
if (stat(filename, &statbuf) == -1) {
    perror("Cannot stat file");
    exit(1);
}

// S_ISREG is a a POSIX macro to check whether the given st_mode denotes a
// regular file. See `man 2 stat'.
if (!S_ISREG(statbuf.st_mode)) {
    fprintf(stderr, "File '%s' is not a regular file\n", filename);
    exit(1);
}
Run Code Online (Sandbox Code Playgroud)

因此,很明显断言这是否是常规文件会导致此错误消息。

有什么作用stat?它检索保存有关所述文件的信息的结构,请参阅man 2 statstaton的调用/dev/null成功,因为文件存在并且可以访问。

为什么是/dev/null常规文件 ( S_ISREG())的断言是假的?因为/dev/null,所谓的Null Device,是内核驱动提供的一种特殊的伪设备文件。写入它的所有内容都将被丢弃,从中读取会立即返回文件结尾。

该目录/dev包含所有设备文件。运行ls -l也将空设备显示为一个特殊文件,用c字符设备表示它(与-常规文件、d目录、l软链接等相反):

$ ls -l /dev/null
crw-rw-rw- 1 root root 1, 3  1. Okt 08:46 /dev/null
Run Code Online (Sandbox Code Playgroud)