IQA*_*eas 118 linux devices files
Linux 中有一些特殊的文件,它们并不是真正的文件。
其中最显着和清晰的例子是在dev文件夹中,“文件”,如:
/dev/null - 忽略您写入文件的任何内容/dev/random - 输出随机数据而不是文件内容/dev/tcp - 通过网络发送您写入此文件的任何数据首先,这些类型的“文件”的名称是什么,它们实际上是某种伪装的脚本或二进制文件?
其次,它们是如何创建的?这些文件是在内核级别内置到系统中的,还是有办法自己创建一个“神奇文件”(a 怎么样/dev/rickroll)?
Mat*_*hid 110
/dev/zero是“特殊文件”的一个例子——特别是“设备节点”。通常这些是由发行版安装过程创建的,但如果您愿意,您可以完全自己创建它们。
如果你问ls有关/dev/zero:
# ls -l /dev/zero
crw-rw-rw- 1 root root 1, 5 Nov 5 09:34 /dev/zero
Run Code Online (Sandbox Code Playgroud)
开头的“c”告诉你这是一个“字符设备”;另一种类型是“块设备”(打印ls为“b”)。粗略地说,硬盘等随机访问设备往往是块设备,而磁带驱动器或声卡等顺序设备往往是字符设备。
“1、5”部分是“主设备号”和“次设备号”。
有了这些信息,我们可以使用mknod命令来制作我们自己的设备节点:
# mknod foobar c 1 5
Run Code Online (Sandbox Code Playgroud)
这将创建一个名为的新文件foobar,在当前文件夹,这不正是同样的事情/dev/zero。(当然,如果您愿意,您可以对其设置不同的权限。)所有这个“文件”真正包含的就是上面的三项——设备类型、主要编号、次要编号。您可以使用它ls来查找其他设备的代码并重新创建这些代码。当你无聊时,只需使用rm删除你刚刚创建的设备节点即可。
基本上,主要编号告诉 Linux 内核要与哪个设备驱动程序通信,而次要编号告诉设备驱动程序您正在谈论哪个设备。(例如,您可能有一个 SATA 控制器,但可能插入了多个硬盘。)
如果您想发明具有新功能的新设备……好吧,您需要编辑 Linux 内核的源代码并编译您自己的自定义内核。所以我们不要那样做!:-) 但是您可以添加与您已有的文件重复的设备文件。像 udev 这样的自动化系统基本上只是监视设备事件并自动为您调用mknod/ rm。没有比这更神奇的了。
还有其他类型的特殊文件:
Linux 将目录视为一种特殊的文件。(通常你不能直接打开一个目录,但如果你可以,你会发现它是一个包含特殊格式数据的普通文件,并告诉内核在哪里可以找到该目录中的所有文件。)
符号链接是一种特殊文件。(但硬链接不是。)您可以使用该ln -s命令创建符号链接。(查找联机帮助页。)
还有一种叫做“命名管道”或“FIFO”(先进先出队列)的东西。您可以使用mkfifo. FIFO 是一个神奇的文件,可以同时被两个程序打开——一个读,一个写。发生这种情况时,它的工作方式就像一个普通的壳管。但是您可以单独启动每个程序...
在任何方面都不“特殊”的文件称为“常规文件”。您偶尔会在 Unix 文档中看到提到这一点。这就是它的意思;一个不是设备节点或符号链接或其他任何东西的文件。只是一个普通的日常文件,没有神奇的属性。
kas*_*erd 35
大多数/dev条目是块设备 inode 或字符设备 inode。维基百科对此有很多细节,我不打算重复。
但是/dev/tcp,您的问题中提到的任何现有答案都没有解释。/dev/tcp并且/dev/udp与大多数其他/dev条目不同。的块和字符设备由内核中实现,但/dev/tcp和/dev/udp在用户模式中实现的。
bash外壳是具有的一个实现一个节目/dev/tcp和/dev/udp(来自复制ksh93)。当您尝试在带有 bash 重定向运算符的路径下打开路径时,它不会执行普通的open系统调用。相反,bash 将创建一个 TCP 套接字并将其连接到指定的端口。
这是在用户模式下实现的,并且仅在某些程序中实现,如下面的示例所示,该示例演示了 letbash和cattry 打开之间的区别/dev/tcp/::1/22
$ cat /dev/tcp/::1/22
cat: /dev/tcp/::1/22: No such file or directory
$ cat < /dev/tcp/::1/22
SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.3
Run Code Online (Sandbox Code Playgroud)
不同之处ksh93在于它bash只会使用重定向操作符执行那些 TCP 连接,而不是在其他可能打开文件的地方,如source或.内置。
Bas*_*tch 21
除了其他答案中解释的设备节点(使用mknod(2)创建或由某些devfs 提供)之外,Linux 还具有由特殊虚拟文件系统提供的其他“神奇”文件,特别是在/proc/(参见proc(5),阅读有关procfs ) 和/sys/(阅读关于sysfs )。
这些伪文件(出现在 -eg stat(2) 中- 作为普通文件,而不是设备)是内核提供的虚拟视图;特别是,读取/proc/(例如cat /proc/$$/maps,在程序中使用或open(2) -ing /proc/self/status)通常不涉及来自磁盘或网络的任何物理 I/O,因此速度非常快。
要在其中创建一些额外的伪文件,/proc/您通常应该编写自己的内核模块并加载它(参见例如this)。
cas*_*cas 13
它们称为设备节点,由 手动mknod或自动创建udev。它们通常是带有内核驱动程序的字符或块设备的类似文件的接口——例如磁盘是块设备,ttys 和串行端口等是字符设备。
还有其他“特殊”文件类型,包括命名管道、fifos 和套接字。
sso*_*low 12
正如其他用户已经详细解释的那样,特殊文件需要代码来备份。然而,似乎没有人提到 Linux 提供了几种在用户空间中编写代码的方法:
A. FUSE(用户空间中的文件系统)允许您编写类似的东西/proc而不会造成内核崩溃的风险,并使用您选择的语言/运行时来执行,例如Go、Node.js、Perl、PHP、Python、 Ruby、Rust,等等。
它还具有 FUSE 文件系统可以在没有安装的情况下安装的优点,sudo因为它们作为执行安装的用户运行。
以下是人们使用 FUSE 编写的一些示例:
B.如果你想创建一个虚拟输入设备,比如键盘、鼠标、游戏杆等(例如,为你正在使用的 USB 设备编写用户空间驱动程序libusb),有uinput。
它的绑定更难找到,但我知道它们存在于Go (Keyboard-only)、Python和Ruby (2)。
实际使用 uinput 的示例包括:
C.对于通用字符设备,有CUSE(用户空间中的字符设备)。虽然它不太受欢迎。
该CUSE的API,我个人知道的唯一用户是促使其创作的同一程序:osspd,它实现/dev/dsp,/dev/adsp以及/dev/mixer在用户空间(OSS的音频API),使他们能够通过的PulseAudio或DMIX路由。
我能找到的唯一 CUSE 绑定是cusepy,它自 2010 年以来一直没有更新。
D.您可能根本不需要新的特殊文件。
例如,您可以使用libusb(页面上的绑定列表)打开与任何 USB 设备的原始通信,然后通过某种其他机制(TCP/UDP 套接字、读/写 stdin/stdout 或磁盘上的常规文件)与其他程序通信, 等等。)。
Linux 设备驱动程序(强烈推荐)一书详细解释了这一点,甚至让您创建了一个内核模块来执行此操作作为示例,但简而言之,每个设备驱动程序都有特定的函数,在打开、关闭文件时会调用这些函数、读取、写入等。“特殊”文件只是在这些函数中做一些特殊的事情,而不是访问磁盘上的存储硬件。
例如, write 函数/dev/null什么都不做,忽略字节。的 read 函数/dev/random返回一个随机数。