让我们快速回顾一下设备文件:在Linux中,应用程序通过文件描述符将rad操作和写操作传递给内核。对于文件的伟大工程,它原来是同一个API可用于字符设备是生产和消费的字符流,块设备,并在随机访问地址,上面写着固定大小的写入块,只是假装这些也是文件。
但是需要一种方法来配置这些设备(设置波特率等),为此,发明了ioctl调用。它只是传递特定于设备的数据结构以及内核使用的I / O控制类型,并以相同的数据结构返回结果,因此它是非常通用的可扩展API,可用于很多事情。
现在,网络运营如何适应?典型的网络服务器应用程序希望绑定到某个网络地址,在某个端口上侦听(例如,对于HTTP为80,对于ssh为22),如果客户端连接,则它希望向该客户端发送数据并从该客户端接收数据。并为客户提供双重操作。
目前尚不清楚如何将其与文件操作配合使用(尽管可以完成,请参阅计划9),这就是UNIX设计人员发明了新API的原因:sockets。您可以在第2节手册页找到细节socket
,bind
,listen
,connect
,send
和recv
。请注意,尽管它与文件I / O API不同,socket
但是该调用还返回了文件描述符。有很多关于如何在网络上使用套接字的教程,谷歌有点。
到目前为止,所有这些都是纯UNIX,没有人在发明套接字时谈论网络接口。而且由于该API确实很旧,因此它为Internet协议(请AF_*
参见常量)之外的各种网络协议定义(尽管Linux中仅支持其中的少数几个)。
但是随着计算机开始获得多个网卡,对此需要一些抽象。在Linux中,这是网络接口(NI)。它不仅用于硬件,而且还用于各种隧道,作为OpenVPN等隧道服务器的用户应用程序终结点。如所解释的,套接字API不基于(特殊)文件并且独立于文件系统。同样,网络接口也不会显示在文件系统中。但是,NI在/proc
和/sys
文件系统(以及其他网络可调参数)中可用。
NI是端点的内核抽象,网络数据包进入和离开内核的端点。另一方面,套接字用于与应用程序通信数据包。数据包的处理不需要套接字。例如,启用转发后,数据包可能会在一个NI上进入而在另一个NI上离开。从这个意义上讲,套接字和网络接口是完全独立的。
但是必须有一种配置NI的方法,就像您需要一种配置块和字符设备的方法一样。而且由于套接字已经返回了文件描述符,因此仅允许ioctl
在该文件描述符上使用是合理的。这就是您链接的netdevice接口。
还有许多其他类似的滥用系统调用的方式,例如用于数据包过滤,数据包捕获等。
所有这一切都在逐步发展,在许多地方并不是特别合乎逻辑。如果同时进行所有设计,则可能会制作出更加正交的API。