趣谈 Linux 操作系统
刘超
前网易杭州研究院云计算技术部首席架构师
84364 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 72 讲
趣谈 Linux 操作系统
15
15
1.0x
00:00/00:00
登录|注册

45 | 发送网络包(上):如何表达我们想让合作伙伴做什么?

上一节,我们通过 socket 函数、bind 函数、listen 函数、accept 函数以及 connect 函数,在内核建立好了数据结构,并完成了 TCP 连接建立的三次握手过程。
这一节,我们接着来分析,发送一个网络包的过程。

解析 socket 的 Write 操作

socket 对于用户来讲,是一个文件一样的存在,拥有一个文件描述符。因而对于网络包的发送,我们可以使用对于 socket 文件的写入系统调用,也就是 write 系统调用。
write 系统调用对于一个文件描述符的操作,大致过程都是类似的。在文件系统那一节,我们已经详细解析过,这里不再多说。对于每一个打开的文件都有一个 struct file 结构,write 系统调用会最终调用 stuct file 结构指向的 file_operations 操作。
对于 socket 来讲,它的 file_operations 定义如下:
static const struct file_operations socket_file_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read_iter = sock_read_iter,
.write_iter = sock_write_iter,
.poll = sock_poll,
.unlocked_ioctl = sock_ioctl,
.mmap = sock_mmap,
.release = sock_close,
.fasync = sock_fasync,
.sendpage = sock_sendpage,
.splice_write = generic_splice_sendpage,
.splice_read = sock_splice_read,
};
按照文件系统的写入流程,调用的是 sock_write_iter。
static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
struct file *file = iocb->ki_filp;
struct socket *sock = file->private_data;
struct msghdr msg = {.msg_iter = *from,
.msg_iocb = iocb};
ssize_t res;
......
res = sock_sendmsg(sock, &msg);
*from = msg.msg_iter;
return res;
}
在 sock_write_iter 中,我们通过 VFS 中的 struct file,将创建好的 socket 结构拿出来,然后调用 sock_sendmsg。而 sock_sendmsg 会调用 sock_sendmsg_nosec。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《趣谈 Linux 操作系统》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(13)

  • 最新
  • 精选
  • 是男人就开巴巴托斯
    有一次分别在服务器端和客户端抓包 服务器端的包都是好几k 十几k. 客户端的包是1400多 一开始没弄明白都mtu了为什么还有好几k的包 后来查到内核可以配置网络参数,不把拆包交给网卡固件,自己分包。

    作者回复: 赞,学以致用

    5
    8
  • 佳俊
    sk_buff已经对mss做了分片处理了,为什么还要在ip再做一次分片处理。sk_buff有最大的限制吗?

    作者回复: 就是mss的限制呀

    3
    1
  • W.jyao
    老师,请教一个问题,为什么流媒体服务器发送的rtp包都要小于1500左右,也就是小于MTU,理论上不是大于1500会分片吗?但是好像实现的代码都会小于Mtu,为什么呢?

    作者回复: 分片再组合会增加时延

    2
    1
  • 一梦如是
    老师好,请教一个困惑很久的问题,cpu的L1,L2,L3级cache,缓存的数据是以内存的页为单位的吗 oracle sga在大内存时,通常会配置hugepage以减少TLB的压力和swap的交换用来提高性能,linux(centos)下默认是2M,而一般cpu L1是32+32K,L2是256K,是不是就意味着没法使用这两级缓存了

    作者回复: Hugepage不会将页面放到缓存里面的,而是TLB缓存减少不命中的概率。

    2
  • 谛听
    VFS: 拿到 file 中的 socket,进而得到 sock,进而调用 tcp_sendmsg tcp_sendmsg: 将用户数据拷到 sk_buff,不断循环发送,发送过程中计算 MSS,拆分成一个个的 Segment 放在一个个的 IP 包里面,数据可拷贝到连续的区域,也可以拷到不连续的区域 ( 需要网络设备支持分散聚合),最后调用 tcp_write_xmit 发送网络包 tcp_write_xmit:TSO--分段可由内核做,比较耗CPU,也延迟到网卡做; 拥塞窗口--避免把网络塞满; 滑动窗口--避免把接收端塞满 tcp_transmit_skb:填充tcp报文,发送网络包
    2
    8
  • 忆水寒
    从网络协议专栏看完过来的,tcp协议实际上很熟悉,所以看这篇文章大概都懂。但是每次读都能有新的体会。
    6
  • stackWarn
    作为一个运维,这节算是这里面听的最轻松的一次了,之前看过这部分的代码,函数名都有点印象哈哈
    1
  • Geek_2b44d4
    请教一下,这里进行分段后,每个段是否时类似链表结构?分包发送的时候,是不是每个包里面都标记了上一个与下一个的标识,这样接收方收到后就可以重排了,不知道是不是这样?
  • 程序员老王
    send 很大数据。假如网络正常,回失败吗?skb回自动增加,没有阻塞和阻塞者 一说吧?
  • herongwei
    老师讲的真的非常好!常看常新
收起评论
显示
设置
留言
13
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部