什么是通用套接字以及它与网络设备有何关系?

什么是通用套接字以及它与网络设备有何关系?

我试图了解网络驱动程序在 Linux 下如何工作。本次问答表明 Linux 中的网络设备不是由设备文件表示的。它指出网络驱动程序与sockets.

例如,参考如何通过ioctl呼叫设置网络设备。ioctl然而需要一个文件描述符,鉴于没有网络驱动程序的设备文件,唯一可以传递的文件描述符是来自套接字的文件描述符。

这让我想到了问题的重点。到目前为止,网络接口(物理网卡的软件表示)实际上是一个比套接字低级的对象。

  • 但从这个抽象意义上讲,套接字是什么?它只是支持推送通知的设备文件的另一个名称吗?我根据用户空间应用程序绑定到网络接口上的地址:端口对的连接点来理解 TCP 套接字。我不明白套接字是设置网络接口的先决条件。

  • Linux 上的网络接口(如eth0列出的ifconfig)可以在没有套接字的情况下存在吗?

  • 某些网络管理器守护程序是否ifconfig保持套接字打开以允许我们设置网络接口选项?

答案1

让我们快速回顾一下设备文件:在Linux中,应用程序通过以下方式向内核传达读写操作:文件描述符。这对于文件来说非常有效,而且事实证明相同的 API 也可以用于字符设备产生和消耗字符流,以及块设备在随机访问地址读取和写入固定大小的块,只需假装它们也是文件。

但是需要一种方法来配置这些设备(设置波特率等),为此,读写控制电话被发明了。它只是传递特定于设备的数据结构和用于内核的 I/O 控制类型,并以相同的数据结构返回结果,因此它是一个非常通用的可扩展 API,可用于很多事情。

现在,网络运营如何适应?一个典型的网络服务器应用程序想要绑定到某个网络地址,在某个端口上(例如 HTTP 为 80,ssh 为 22),并且如果客户端连接,它想要发送数据至 和收到来自该客户端的数据。并为客户端进行双重操作。

如何将其与文件操作相适应并不明显(尽管可以做到,请参阅计划9),这就是 UNIX 设计者发明新 API 的原因:插座。您可以在socketbindlistenconnectsend的第 2 部分手册页中找到详细信息recv。请注意,虽然它与文件 I/O API 不同,但该socket调用仍然返回一个文件描述符。网上有很多关于如何使用套接字的教程,google一下。

到目前为止,这都是纯粹的 UNIX,在发明套接字时没有人谈论网络接口。而且因为这个 API 确实很旧,所以它是为 Internet 协议之外的各种网络协议定义的(查看常量AF_*),尽管 Linux 中只支持其中的一小部分。

但随着计算机开始配备多个网卡,需要对此进行一些抽象。在 Linux 中,那就是网络接口(你)。它不仅用于硬件,还用于各种隧道,以及充当 OpenVPN 等隧道的用户应用程序端点。正如所解释的,套接字 API 不基于(特殊)文件,并且独立于文件系统。同样,网络接口也不会出现在文件系统中。但是,NI 在文件/proc系统/sys(以及其他网络可调参数)中可用。

NI 是网络数据包进入和离开内核的端点的简单内核抽象。另一方面,套接字用于与应用程序进行数据包通信。不需要套接字参与数据包的处理。例如,当启用转发时,数据包可能会在一个 NI 上进入并在另一个 NI 上离开。从这个意义上说,套接字和网络接口是完全独立的。

但是必须有一种方法来配置 NI,就像您需要一种方法来配置块和字符设备一样。由于套接字已经返回了一个文件描述符,因此只允许ioctl该文件描述符上的一个在某种程度上是合乎逻辑的。这就是网络设备您链接的界面。

还有很多其他以类似方式滥用系统调用的行为,例如数据包过滤、数据包捕获等。

所有这一切都是一点一点地发展起来的,而且在很多地方并不是特别合乎逻辑。如果一次性设计出来,人们可能会制作出更加正交的 API。

相关内容