从程序员的角度来看,外部设备在unix中不过是普通的文件,通过正常的读写操作即可访问。但是对于网卡而言情况有些复杂。因为上述方案或者根本不能采用,或者会带来极大的困难。网卡的运作方式与普通的块设备和字符串完全不同。一个原因是(所有层次)使用了许多不同的通信协议,为建立连接所需要制定许多选项,且无法打开设备文件时完成这些任务。因此在/dev目录下没有与网卡对应的项。
在20世纪80年代BSD unix程序员采用一种称为套接字的特殊结构作用到网路实现的接口,这种方案现在已经成为工业标准。POSIX标准中也定义了套接字,因而Linux也实现了套接字。
套接字现在用于定义和建立网络连接以便可以使用inode的普通方法(读写操作)来访问网络。从程序员的角度上看,创建套接字的最终结果是一个文件描述符,它不仅提供所有的标准函数还包括几个增强的函数。用于实际数据交换的接口对于所有的协议和地址族都是同样的。
在创建套接字的时候不仅要区分地址和协议族还要区分基于流的通信和数据报的通信。(对面向流的套接字来说)同样重要的一点是套接字是为客户端程序建立的还是为服务端程序建立的。
##创建套接字
套接字不仅可以用于各种传输协议的ip连接,也可以用于内核支持的所有其他地址和协议类型(例如IPX、Appletalk、本地unix套接字、DECNet等等。)目前每个地址族都只支持一个协议族,而且只能区分面向流的通信和面向数据报的通信。套接字是使用socket库函数生成的。除了地址族和通信类型支持,可以使用第三个参数来选择协议,但是这是不必要的因为前两个参数已经唯一定义了协议,将第三个参数指定为0,即通知函数使用适当的默认协议。
CPU存储数值有两种惯例即大端序和小端序,为确保不同字节序的机器之间能够彼此通信显示定义了一种网络字节顺序,他等价于大端序。因此协议首部出现的数值都必须使用网络字节。
内核在分配输入和输出TCP/IP分组时必须注意到四元组的所有4个分量才能确保正确该任务成为多路复用。
数据报套接字
- UDP是面向分组的,在发送数据之前无需建立显示的连接
- 分组可以在传输期间丢失,不保证数据一定能到达其目的地
- 分组接受的次序不一定能够与发送的次序相同
分别使用TCP和UDP协议的金城可以同时使用相同的IP地址和端口号,在多路复用时内核会根据分组的传输协议类型将其转发到适当的进程。
##套接字缓冲区
在内核分析收到的网络分组时,底层协议的数据将传递到更高的层。发送数据时顺序相反,各种协议产生的数据(首部和净荷)依次向更低层传递直至最终发送。这些操作的速度对于网络子系统的性能有着决定性的影响因此内核采用的一种特殊的结构成为套接字缓冲区。套接字缓冲区用于在网络实现的各个层次之间交换数据而无需来回复制分组数据对性能的提升很可观。
##网络访问层
- 网络设备的表示
在内核中每个网络设备都表示为net_device的一个实例,在分配并填充该结构的一个实例之后必须调用net/core/dev.c中的regeister_netdev函数将其注册到内核中去。
网络设备的命名
设备名称 | 设备类别 |
---|---|
ethX | 以太网适配器 |
pppX | 通过调制解调器建立的PPP连接 |
isdnX | ISDN卡 |
atmX | 异步传输模式,高速网卡接口 |
lo | 环回设备用于本地计算机通信 |