Linux内核如何知道以太网冲突域中发生了冲突?

Linux内核如何知道以太网冲突域中发生了冲突?

假设我有以下网络拓扑:

集线器设置

所有四台主机的理论总(Tx + Rx)带宽总计为 100Mbps。现在如果我执行伊珀夫同时在所有四台主机上处于 UDP 模式,并强制每个 Iperf 实例-b 50m在线路上传输 50Mbps(在 Iperf 客户端中)的流量,然后 Iperf 不会在线路上传输那么多流量。这是因为 NIC 接收到冲突,因此 Iperf 客户端接收到一些对 UDP 套接字-1的系统调用的返回值。write()虽然我了解内核和 Iperf 客户端如何通信,但我不太了解 NIC 和内核如何通信。 NIC 驱动程序(tg3适用于我的 BCM5721 NIC)是否会发生这种情况?是否有某种系统调用通知内核发生了冲突?

答案1

内核和 NIC 的通信方式与内核(具体来说,设备驱动程序,它是内核的一部分)与任何其他设备(例如,串行通信设备(如键盘、鼠标或 RS232)、磁盘(或磁盘)通信的方式相同。 - 如大容量存储设备)、显示器、安全令牌等)——它们直接相互通信。所以,是的,这发生在 NIC 驱动程序中。不,驱动程序↔设备通信不通过系统调用。

设备驱动程序与设备通信通常通过两种访问方法:内存映射 I/O (MMIO) 和端口映射 I/O (PMIO)。这些在 上进行了详细的描述和讨论超级用户 在这两个问题中:

也可以看看什么是驱动程序,它是如何工作的? 如果您需要背景信息。顺便说一句,使用哪种访问方法是由计算机体系结构决定的。例如,维基百科说,“内存映射 I/O 是首选x86基于架构……”

回到你的具体问题,如果我们假设内存映射 I/O,驱动程序可以测试与 C 代码的冲突,就像这样简单

        if (nic->error_status & 碰撞)
        {
                // 如果发生碰撞,我们就到这里。
                (处理碰撞的代码)
        }

(其中nic是指向 NIC 映射地址的指针),对于驱动程序来说,导致错误从系统调用返回到用户进程是一件微不足道的事情write()


后续问题:

驱动程序是内核的一部分这一事实是否意味着不存在驱动程序↔内核通信方法?

这可能几乎值得作为另一个问题来问(或者至少做一些更多的研究;即网络搜索)。最初,Unix核心曾是整体式的 (也可以看看整体内核)。内核和驱动程序之间的关系就像人体和双手之间的关系——手是与众不同, 永远不会与肘部或肺部等混淆,但它们是身体不可分割的一部分。

即使在有四个的机器上保护环,Unix 仅使用了两个 — 内核位于环 0 中,用户区位于环 3 中。 还有其他操作系统,其设备驱动程序类似于刀叉 — 删除了一级(例如,驱动程序位于中间环之一(1 和 1)。 /或2))。我没有跟上 *nix/Linux 的所有发展(例如,线性KM),并且某些 unice 的基本内核和驱动程序之间的分离程度可能比其他 unice 更大。例如,参见

正如我所说,这些东西位于我知识库的边缘;不要再问我任何关于上述问题的后续问题。

而且,这个问题在语义上是不明确的。身体与手有交流吗?是的,通过神经系统(在某种程度上,通过骨骼)。 “内核”是否与设备驱动程序(属于内核的一部分)通信?是的,就像 C 程序(例如,,,,,等)与 C 库通信一样——cat通过子例程调用(也许偶尔、明智地使用全局变量)。当用户进程调用与I/O相关的系统调用(例如,,,,,,等) 时,通用系统调用处理代码(在内核中)调用适当的设备驱动程序例程(可能带有一些中间逻辑)。文件系统相关的代码还调用适当的磁盘驱动程序例程。并且内核至少有助于在接收到中断时调用特定于设备的中断处理程序(实现各不相同)。cplssedopen()close()read()write()ioctl()poll()select()

相关内容