Linux 核心--11.网络( 四 )



proto_ops 结构由地址族类型和一系列指向与特定地址族对应的socket操作例程的指针组成 。pops 向量通过地址族标识符来索引,如Internet地址族标识符(AF_INET是2) 。





图 10.3: Linux BSD Socket 数据结构


10.4INET Socket 层
INET socket层支持包括TCP/IP协议在内的internet地址族 。如前所述,这些协议是分层的,一个协议使用另一个协议的服务 。Linux的TCP/IP代码和数据结构反映了这一分层模型 。它与BSD socket层的接口要通过一系列Internet地址族socket操作,这一操作是在网络初始化时就已经注册到BSD socket层的 。这些都与其它已注册的地址族一起保存在 pops 向量中 。BSD socket层从已注册的INET proto_ops 数据结构中调用INET层 socket支持例程来为它执行工作 。例如,一个地址族为INET的BSD socket建立请求,将用到下层的INET socket的建立函数 。在这些操作中,BSD socket层把用来描述BSD socket的 socket 结构传构到INET层 。为了不把BSD socket 与TCP/IP的特定信息搞混,INET socket层使用它自己的数据结构,sock,它与BSD socket 结构相连 。这一联接关系可以从图10.3 中看出 。它用BSD socket的 data 指针来连接 sock 结构与BSD socket结构 。这意味着后来的INET socket调用能够很容易地重新找到 sock 结构 。sock 结构的协议操作指针也在初始化时建立,它依赖与被请求的协议 。如果请求的是TCP,那么 sock 结构的协议操作指针将指向TCP连接所必需的TCP协议操作集 。


10.4.1建立BSD socket
系统建立一个新的socket时,通过标识符来确定它的地址族,socket类型和协议 。

首先,从 pops 向量中搜索与被请求的地址族相匹配的地址族 。它可能是一个作为核心模块来实现的一个特定的地址族,这样,在其能继续工作前,kerneld 守护进程必须加载这一模块 。分配一个新的 socket 结构来代表BSD socket 。实际上 socket 结构是 VFS inode 结构的一部分,分配一个socket实际上就是分配一个 VFS inode。除非你认为socket操作能和普通的文件操作一样,否则会觉得这好象很奇怪 。所有的文件用VFS inode结构来表示,为了支持文件操作,BSD socket必须也用 VFS inode 来表示 。

最新建立的 BSD socket 结构包含一个指向地址族特定socket例程的指针,可以用来从 pops 向量中找到 proto_ops 结构 。它的类型被设置成被请求的socket类型:SOCK_STREAM,SOCK_DGRAM等等之一 。调用地址族特定创建例程使用保存在 proto_ops 结构中的地址 。

从当前过程 fd 向量中分配一个自由的文件描述符,对 file 结构所指向的进行初始化 。包括将文件操作指针设置为指向由BSD socket接口支持的BSD socket文件操作集 。任何操作将被引到socket接口,通过调用它的地址族操作例程将它们传到支持的地址族 。

10.4.2将地址与INET BSD socket绑定
为了能监听输入的internet连接请求,每个服务器必须建立一个INET BSD socket,并将地址与其绑定 。绑定操作主要在INET socket层内处理,下面的TCP和UDP协议层提供一些支持 。与一个地址绑定了的socket不能用来进行任何其它的通讯工作,也就是说:socket的状态必须是 TCP_CLOSE。sockaddr 结构包含了与一个任意的端口号绑定的IP地址 。通常绑定的IP地址已经分配给了一个网络设备,该设备支持INET地址族且其接口是可用的 。可以在系统中用ifconfig命令来查看哪一个网络接口是当前激活的 。IP地址也可以是广播地址,全1或全0 。这是些特定的地址,用以表示发送给任何人3 。如果机器充当一个透明的代理或防火墙,则IP地址可被指定为任一个IP地址,但只有有超级用户权限的进程能绑定到任何一个IP地址 。绑定的IP地址被存在sock结构中的 recv_addr 和 saddr 字段 。端口号是可选的,如果没有指定,将任意指定一个 。按惯例,小于1024的端口号不能被没有超级用户权限的进程使用 。如果下层网络没有分配端口号,则分配一个大于1024的端口号 。

推荐阅读