44 | Socket内核数据结构:如何成立特大项目合作部?
刘超
该思维导图由 AI 生成,仅供参考
上一节我们讲了 Socket 在 TCP 和 UDP 场景下的调用流程。这一节,我们就沿着这个流程到内核里面一探究竟,看看在内核里面,都创建了哪些数据结构,做了哪些事情。
解析 socket 函数
我们从 Socket 系统调用开始。
这里面的代码比较容易看懂,Socket 系统调用会调用 sock_create 创建一个 struct socket 结构,然后通过 sock_map_fd 和文件描述符对应起来。
在创建 Socket 的时候,有三个参数。
一个是 family,表示地址族。不是所有的 Socket 都要通过 IP 进行通信,还有其他的通信方式。例如,下面的定义中,domain sockets 就是通过本地文件进行通信的,不需要 IP 地址。只不过,通过 IP 地址只是最常用的模式,所以我们这里着重分析这种模式。
第二个参数是 type,也即 Socket 的类型。类型是比较少的。
第三个参数是 protocol,是协议。协议数目是比较多的,也就是说,多个协议会属于同一种类型。
常用的 Socket 类型有三种,分别是 SOCK_STREAM、SOCK_DGRAM 和 SOCK_RAW。
SOCK_STREAM 是面向数据流的,协议 IPPROTO_TCP 属于这种类型。SOCK_DGRAM 是面向数据报的,协议 IPPROTO_UDP 属于这种类型。如果在内核里面看的话,IPPROTO_ICMP 也属于这种类型。SOCK_RAW 是原始的 IP 包,IPPROTO_IP 属于这种类型。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入剖析了Socket系统调用的内部实现细节,包括创建Socket、监听和接受连接的过程。通过介绍Socket系统调用的代码实现和相关参数含义,详细讲解了创建Socket时涉及的地址族、类型和协议,以及对应的数据结构和初始化过程。特别关注了SOCK_STREAM类型和IPPROTO_TCP协议的创建过程,以及在内核中对应的数据结构和函数调用。此外,还介绍了bind、listen和accept等函数的实现细节,包括在内核中的具体调用过程和相关数据结构的操作。通过对关键代码的解析,读者可以深入了解Socket系统调用的内部实现细节,包括TCP连接的建立和监听过程。总体而言,本文对Socket系统调用的内部工作原理进行了深入剖析,为读者提供了深入理解网络编程底层原理的重要参考资料。对于对网络编程底层原理感兴趣的读者来说,本文是一份重要的参考资料。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《趣谈 Linux 操作系统》,新⼈⾸单¥68
《趣谈 Linux 操作系统》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(12)
- 最新
- 精选
- 莫名看了一遍,然后花了一天把源码又过了一遍,很有收货,对socket的理解不再浮于表面。
作者回复: 赞
2019-08-0913 - kkxue原来得先看总结图,再看内容。。
作者回复: 对的,这是一个好方法
2019-07-145 - W.jyao老师,能解释下listenfd和acceptfd的端口为什么一样吗?
作者回复: 一个服务端口当然一样呀。只不过两个socket数据结构而已
2019-07-083 - 无心之福开头的那个代码的 逗号加的不对吧?
作者回复: 对的,看一下SYSCALL_DEFINE3这个宏的定义就理解了
2019-08-1921 - book尾汁调用accept的时候,会新建一个socket,以及其对应的struct file,然后会从icsk_accept_queue 取出一个req,将其sk赋值给新建的socket->sk,这样就可以读取到请求的数据了,不理解的是后面讲到接收数据包时tcp层有三个队列,会根据内核低延时 高吞吐量的等策略以及socket当时的状态来决定放入哪个队列,这里的socket是怎么选出来的啊,数据包是先发送到处于监听队列的socket然后由其将数据分发到其通过accept生成的sokcet上吗,如果是直接由通过accept生成的socket来处理,怎么分辨出来到底该给哪个socket呢,根据数据包的源地址与端口吗?
作者回复: 监听的端口号
2020-05-032 - 飞翔syn到底是个什么东西呀?是个integer还是char类型
作者回复: 详见网络包的格式,TCP头里面有syn
2019-07-083 - 二星球老师好,同一个TCP链接上先后发送2次rpc请求,后发送的请求其结果先返回,先发送的请求结果后返回,这样有没有问题呢,系统能区分各自的返回结果么,靠什么机制保证的呢?一直没有想明白
作者回复: RPC是应用层的,需要应用层自己保证请求和结果的对应。
2019-07-082 - 奔跑的码仔struct tcp_sock继承自struct inet_connection_sock inet_conn,inet_connection_sock继承自struct inet_sock,struct inet_sock继承自struct sock; 1.上述四个结构的关系具有十足的面向对象的特征,struct是基类,通过层层继承,实现了类的复用; 2.内核中网络相关的很多函数,参数往往都是struct sock,函数内部依照不同的业务逻辑,将struct sock转换为不同的业务结构; 这样做的好处: 1.简化接口的设计复杂度; 2.使用基类作为参数,十分类似于面向对象中的多态特性,能够有效的增强接口的稳定性、提升扩展性。2019-10-1115
- 谛听socket: 根据参数创建相应socket bind: 绑定IP、端口 listen: 建立两个队列,改变状态为TCP_LISTEN accept: 从完成三次握手的队列中取出一个socket,没有的话让出cpu connect: 三次握手2019-11-246
- Geek_ty老师您好,我在认真阅读了文章和代码后还是存在一个疑惑:icsk_accept_queue是全连接队列当然没有问题,但是服务端LISTEN状态下,调用tcp_v4_conn_request()时inet_csk_reqsk_queue_hash_add()函数也是增加了该队列的长度。但是实际上应该修改的时半连接队列才对。我反复看了几遍源码,没有发现在什么地方有保存syn队列,也没有syn队列的相关操作,都是对icsk_accept_queue的操作,这让我十分困惑,还请老师帮忙解答。2020-08-081
收起评论