- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
深入剖析网络发送过程
深入剖析网络发送和接收过程
本文在基于以下三个条件所写的:
OSI七层网络通信模型。
所阐述的函数是基于Linux2.6.1内核。
在面向连接的通信协议TCP/IPV4的基础上。
由于七层模型(应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 应用层Application Layer), 传输层Transport Layer), 网络层Network Layer), 数据链路层Data Link Layer), 物理层Physical Layer).其中七层模型中的前三层都归结为五层结构中的应用层。为了简化讨论,本文主要从这五层结构来探讨。
Layer 5:应用层(Application Layer)
在TCP协议上,当通过三方握手建立了连接之后,就进入数据包的实质发送阶段,在本文中以send命令来阐述。当通过send将数据包发送之后,glibc函数库会启用另外一个其定义的别用名函数__libc_sendto(),该函数最后会间接执行到sendto系统调用:
inline_syscall##nr(name, args);// ##nr说明是该系统调用带有nr个args参数sendto系统调用的参数值是6,而name就是sendto
从上面的分析可以看出glibc将要执行的下面一条语句是
inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6)
在该函数中一段主要功能实现代码如下:
__asm__ __volatile__ \
(callsys # %0 %1 = %2 %3 %4 %5 %6 %7 %8 \
: inline_syscall_r0_out_constraint (_sc_0), \
=r(_sc_19), =r(_sc_16), =r(_sc_17), \
=r(_sc_18), =r(_sc_20), =r(_sc_21) \
: 0(_sc_0), 2(_sc_16), 3(_sc_17), 4(_sc_18), \
1(_sc_19), 5(_sc_20), 6(_sc_21) \
: inline_syscall_clobbers); \
_sc_ret = _sc_0, _sc_err = _sc_19;
该代码采用了嵌入汇编(详细介绍查阅嵌入汇编相关书籍),其中:
_sc_0=sendto;
_sc_19 --_sc_21分别是arg1—arg6;
inline_syscall_r0_out_constraint:功能相当于=r,选用一个寄存器来存储输出变量。
0--6分别是%0--%6,代表_sc_0--_sc_21
接下来函数最终通过Linux中顶顶有名的INT 0X80陷入系统核心。具体的过程可以参考内核相关书籍。下面是一个兄弟对INT 0X80的简要介绍:
/u2/65427/showart_712571.html
在陷入系统内核以后,最终会调用系统所提供的系统调用函数sys_sendto(),该函数直接调用了__sock_sendmsg(),该函数对进程做一个简单的权限检查之后就触发套接字(socket)中定义的虚拟sendmsg的函数,进而进入到下一层传输层Layer 4: 传输层Transport Layer)
由上层的讨论可知,系统触发了sendmsg虚拟接口函数,其实就是传输层中的tcp_sendmsg或是udp_sendmsg,看你所使用的协议而定。本文介绍tcp_sendmsg().
该函数需要做如下工作:
为sk_buff(后面简称skb)分配空间,该函数首先尝试在套接字缓冲队列中寻找空闲空间,如果找不到就使用tcp_alloc_pskb()为其重新分配空间。
下面这步就会tcp_sendmsg函数的主要部分了,将数据拷贝到缓冲区。它分为如下两种情况:
2.1)如果skb还有剩余空间的话,就使用skb_add_data()来向skb尾部添加数据包。代码如下:
if (skb_tailroom(skb) 0) {
/* We have some space in skb head. Superb! */
文档评论(0)