第十五章 发送和接收数据包
15.1 内核的发送/接收函数
send()/recv(), sendto()/recvfrom(), sendmsg()/recvmsg()
a. 以上函数经过glibc及内核的宏替换映射到sys_socketcall()系统调用的sys_send()/sys_sendto()/sys_sendmsg()/sys_recv()/sys_recvfrom()/sys_recvmsg()
b. sys_send()-->sys_sendto()-->sock_sendmsg(). 即3对函数都集中在sock_sendmsg()和sys_recvmsg()
c. write()/read()对应系统调用sys_write()/sys_read()-->vfs_write()/vfs_read()-->do_sync_write()/do_sync_read()-->sock_aio_write()/sock_aio_read()-->do_sock_write()/do_sock_read()-->......
.....-->__sock_sendmsg()/__sock_recvmsg()
15.2 客户端发送数据包
struct msghdr {
....
};
struct iovec {
.....
};
struct sock_iocb {
.....
};
__sock_sendmsg()-->tcp_sendmsg()-->tcp_write_queue_tail()
-->tcp_send_head()
-->select_size()缓冲区大小
-->skb_entail()-->tcp_add_write_queue_tail()
-->skb_add_data()
-->skb_copy_to_page()-->sk_mem_charge()-->sk_has_account()
-->forced_push()
-->tcp_mark_push()
-->__tcp_push_pending_frames()-->tcp_write_xmit()-->tcp_mtu_probe()
-->tcp_cwnd_test()-->tcp_packets_in_flight()
-->tcp_event_new_data_sent()-->tcp_advance_send_head()
-->tcp_send_head()
--> tcp_push_one()-->tcp_init_tso_segs()-->tcp_set_skb_tso_segs()
-->tso_fragment()-->tcp_fragment()-->skb_split()-->skb_split_inside_header()
-->skb_split_no_header()
-->tcp_insert_write_queue_after()
-->tcp_transmit_skb()
tcp_sendmsg()完成数据包的发送
tcp_write_queue_tail()获取sock发送队列中的数据包
tcp_send_head()发送头指向的数据包
select_size()缓冲区大小. 分配新的skb的数据包结构空间时
skb_entail()将数据包链入到sock结构的发送队列
tcp_add_write_queue_tail()将数据包链入sock发送队列的尾部
skb_add_data()将客户端程序数据复制到缓冲块中,形成数据块.
skb_copy_to_page()将应用程序数据复制到内存页面中
forced_push()检查发送序号主是否在PUSH序号的最大范围内
tcp_mark_push()设置PUSH标志. 将PUSH序号设置为发送序号
__tcp_push_pending_frames()发送数据包
tcp_send_head()是否急需发送的数据包?
tcp_push_one()检查拥塞情况,分段发送数据包, 分段后的数据包留在发送队列, 下一次循环复制用户后发送
tcp_init_tso_segs()初始化TSO分段数
tso_fragment()将原数据包分段到新的数据包,并将新数据包链入到发送队列.
tcp_fragment()数据包分段处理. 收缩原数据包,多余数据放在新数据包中.
skb_split()分隔/转嫁超出部分到新数据包
skb_split_inside_header()分隔基本数据块, 转嫁分散数据块到新数据包
skb_split_no_header()将分散数据块转嫁/分隔到新数据包
tcp_mtu_probe()检查MTU
tcp_cwnd_test()计算阻塞限额. 根据窗口规定的阻塞要求计算还能发送的数据包数量.
tcp_event_new_data_sent()准备发送下一数据包
tcp_advance_send_head()调整发送头,使其指向下一个数据包.
......待深入理解
15.3 服务器接收数据包
阅读(1207) | 评论(0) | 转发(0) |