BSD socket
2006-08-09 22:57:07 来源:WEB开发网从函数整体来看, 函数有三重 do 循环, 第一层要解决把一个大于 sockbuf 容量的消息分块发送 (分成不同的报文) 的问题, 第二层是要解决把读到的数据分成一个个 mbuf 存放的问题, 最里一层是要处理从 uio 多次读数据才能填充好一个 mbuf 问题. 通过这种方法解决了各层机构容量不匹配的问题.
soreceive()
无论是 recv(2), 还是对 socket fd 的 read(2), 最终都是调用 uipc_socket.c: soreceive() 来完成.
首先读读前面的注释, 我们再来看它的实现. 我们首先要以 PEEK 方式 (读数据而不取下 mbuf) 读取带外数据, 然后, 若缓冲区中的数据不够我们所要求的, 我们将等待 (line 989 - 1036).
运行到达 dontblock 标记处时, 我们要开始真正的读缓冲过程. 这是 m 指向我们要读取的 mbuf 链. 注意现在缓冲区中的 mbuf 可能分数几个不同的 packet, 这由 mbuf 头部的 m_nextpkt 提供, 在这里开始由 nextrecord 指向. 根据协议要求, 在真正读数据之前, 我们可能首先要读出地址信息 (line 1051 - 1074), 和控制信息 (1075 - 1101). 如果除此以外我们还有数据, 我们把数据的起始作为报头, 提取信息, 然后在 line 1137 的 while 处开始真正的读数据过程.
获取本次需要读取的长度后, 我们在 1165 真正把数据从 mbuf 中读出, 在 1187 处, 如果我们已经把一个 mbuf 中的数据读完, 就删掉这个 mbuf, 并专向下一个 --- 此时, 如果我们已经把一个 packet 读完, 我们会转向下一个 packet, 即下一个 mbuf 链. 接下来, 如果还没读够数据, 我们可能要通知底层实现读入更多数据 (line 1269) 并等待数据的到来 (line 1277) 数据读取的过程便这样循环完成.
最后是收尾工作. XXX. 其实没设呢么好注意的.
更多精彩
赞助商链接