就此而言,.net 中的一堆静态文件到底有什么问题/dev?对于开发人员来说,我现在重新发明这个轮子 3 次(devfs-> udev + HAL-> udev)显然不够令人满意,现在显然它也进入了 Grand Unified Init Program,所以四次。
我记得几年前我第一次开始使用 Linux 时感到惊讶,尽管声称“一切都是文件”,但没有/dev/eth0(后来是有道理的,因为它不是字符或块设备——尽管是“数据包”设备类型会很有趣...)。鉴于此,为什么处理字符和块设备文件树的程序还要负责网络设备?我已经看到对“灵活性”的模糊引用,但是这对 ifconfig(8) 仅通过查看所做的事情有何补充/proc/net/dev?例如,我知道 NetworkManager 不会很快出现在 Net 或 OpenBSD 中,因为它依赖于udev,这两个团队都不想编写;我不知道的/dev内核已经以多种方式公开了它们(并且它们都没有/dev!)。
仅仅是因为热插拔吗?内核只是侦听物理总线并在“添加设备”消息上加载适当的模块是否存在问题?或者,上帝保佑,实际管理员这样做?我确实记得早在 2000 年代初期,我的服务器有时会以意想不到的顺序初始化它们的网卡,我认为在用户空间中决定命名是有意义的(尽管当时修复并不是非常困难),但是这对蟑螂来说似乎是一把大锤。(或者,这个问题可能会影响到我认为比机架式服务器或 PC 更难的用例,这是我的经验。)
所以,简单地说一下我的问题:udev 实际解决了什么问题,devfs、HAL 和/或普通旧文件如何无法解决这些问题?许多不同的东西(热插拔、通用设备管理、网络设备管理、设备命名、驱动程序优先级等)都成为一个程序是否有特殊原因?
der*_*ert 33
还有两件事:Linux 进入企业和其他大型服务器暴露/dev了要打破的静态。消费者和企业的先进技术正在将静态 /dev 暴露为一个笑话。[这个答案填补了更多的背景故事,而不是特别说明为什么 devfs 被 udev 取代]。
/dev文件在内核中通过它们的主要和次要编号来识别。内核实际上从来没有关心过这个名字(例如,你可以,mv /dev/sda /dev/disk-1而且它会继续工作——当然程序不知道在哪里找到它)。
使用 static /dev,您需要为每个可能存在的潜在设备分配一个主要/次要编号。这些数字需要在全球唯一,因为它们是作为发行版的一部分提供的,而不是按需创建的。问题是它们都是 8 位数字——范围是 0-255。
最初,例如,Linux 开始时 8,0 是 sda,8,1 是 sda1,8,16 是 sdb,等等。但是人们不断向机器添加越来越多的磁盘,尤其是当您考虑光纤通道之类的东西时。因此,在某些时候,为更多磁盘添加了主编号 65-71。后来,主要数字 128-135。然而人们一直想要更多的磁盘......
像 GPT 这样的分区表格式出现了,支持每个磁盘更多的分区。当然,其他设备也在消耗数字空间:各种 RAID 控制器、逻辑卷管理等。
最终结果可以在LANANA Linux 设备列表中看到。如果您查看 2.6 列表(唯一仍然存在的列表),会使用到 200(最大:255)的许多块主要编号。显然,这些数字已经用完了。
更改为更大的数字并不容易。它改变了内核 ABI。根据文件系统,它会更改磁盘布局。但是,当然,大多数这些设备并不存在于任何一个系统上,即使是(例如)用完 SCSI 磁盘的系统也可能有很多免费的东西——它可能不需要 IBM XT 硬盘,例如。
使用 dynamic /dev,发行版不必提供设备编号。它们不再必须是全球唯一的。它们甚至不必在靴子中都是独一无二的。
过去很容易为所有东西分配一个数字。一块板有两个 IDE 通道;每个 IDE 通道支持一个主设备和一个从设备。您可以按通道顺序进行分配,也可以按主从顺序进行分配。所以hda成为第一通道,主人;hdb第一通道,奴隶;hdc第二个通道,主;等等。那些是可预测的和稳定的。如果您添加一个新驱动器或移除一个驱动器,它们可能会发生变化,但如果没有硬件更改,它们是静态的。
你可以把/dev/hda1你/etc/fstab并相信它会留下来工作,至少不存在硬件更改。
IDE 就是这样工作的。做完之后就什么都没有了。
SATA 看起来很简单:一个端口,一个磁盘。但并非如此;它允许端口倍增器。它允许热插拔。尽管如此,如果没有硬件更改,您实际上仍然可以保持映射工作。
USB 差很多。它不仅允许热插拔,而且是典型的。人们一直在插入 USB 闪存驱动器。此外,设备可能需要一段时间来探测——并且实际上可以随时更改(例如,在手机上打开或关闭 USB 存储模式时)。火线是类似的。两者都不能真正想出一个稳定的映射。
网络附加磁盘没有任何固有的端口顺序。内核使用的唯一顺序是它们出现的顺序。逻辑卷也是如此。
对启动速度的追求也让事情变得更糟。最初,内核会很高兴地坐在那里等待相当长的时间,例如所有 USB 设备的初始化。全面探测所有 SCSI 总线等。这些探测被制成后台任务;引导将不再等待他们。当探针完成时添加设备。
所以内核或多或少地留下了“它们出现的任何顺序”。这意味着许多类型的设备可以并且确实在每次启动时更改顺序——在一次启动/dev/sdb中的内容在另一次启动中/dev/sdc。这使得静态的想法成为/dev一个笑话。
当您将/dev由于不可预测的设备探测顺序而变得越来越无意义的静态组合以及继续分配静态主/次编号导致大量工作没有用完时,Linux 开发人员选择切换到动态/dev.
Mar*_*iae 23
好问题。
在某种程度上,这个论点可以扭转:由于内核 2.6.13 引入了 的新版本uevent,因此必然会发生devfs需要重新编写以利用接口的新功能的情况。因此,在某种程度上,问题应该是为什么要更改内核。
然而,从表面上看,你的问题在这篇维基百科的文章中得到了回答:
与传统的 Unix 系统不同,/dev 目录中的设备节点是一组静态文件,Linux udev 设备管理器动态地仅为系统上实际存在的设备提供节点。尽管 devfs 曾经提供类似的功能,但 Greg Kroah-Hartman 列举了许多偏爱其实现而不是 devfs 的原因:
1) udev 支持持久设备命名,它不依赖于例如设备插入系统的顺序。默认 udev 设置为存储设备提供持久名称。任何硬盘都可以通过其唯一的文件系统 ID、磁盘名称以及它所连接的硬件上的物理位置来识别。
2) udev 完全在用户空间执行,而不是在 devfs 的内核空间。一个后果是 udev 将命名策略移出内核,并且可以在创建节点之前运行任意程序,根据设备的属性为设备组成一个名称;在那里,整个过程也是可中断的,并且以较低的优先级运行。
我可能应该补充一点,使用 udevrace condition可以避免a 的可能性,这基本上破坏了 devfs 和 hotplug 中设备的命名。换句话说:使用 devfs 无法确保最左边的以太网端口eth0和最右边的以太网端口被调用eth1,这使得(作为一个纯粹的例子)路由器的设置(一个端口到 WAN,一个端口到 LAN)很难实施。
采用基于 GUID 的磁盘命名方案是另一个优点,将整个过程移至用户空间更大的一个:您是否通过该站点搜索过有多少人编写了自己的 udev 规则?
作为在用户空间中使用 udev 的固有优势的一个简单示例,请在此站点上查看此问题或此其他问题。