Linux socket

本文深入解析BSDsocket与INETsocket的工作原理,包括socket创建、地址绑定、监听、连接及接受连接请求的过程。通过详细步骤展示socket从应用层到内核层的调用流程,以及TCP/IP协议层如何实现这些操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

创建一个BSD socket:

  1. socket()函数,利用sys_socket ()系统调用.(应用层)
  2. sys_socket ()调用sock_socket()申请一个socket数据结构并且填入相应的值。由于socket是inode数据结构的一部分,所以申请一个socket实际上是申请一个空白的inode,注册自己的文件操作集proto_ops,其包含了几乎所有的协议操作函数(release、bind、connect、accept、listen等),这组函数由下层INET协议提供。(表示层 BSD socket,进入内核)
  3. BSD socket层使用由下层具体协议族提供的相关的socket创建函数inet_create() 创建sock结构并且初始化下层提供的操作函数。(会话层 INET socket 层)
sock->prot = &tcp_prot;
sock->ops = &inet_stream_ops;

【在 sock 结构中的协议操作集, 是一个 proto 数据结构, 其间定义了 TCP/IP 协议层对 proto_ops 操作集的实现。INET 协议层利用这组函数实现自己的操作。TCP/IP 协议层对 proto 数据结构有三种实现: tcp_prot、udp_prot、 raw_prot。】
【TCP/IP协议层与网络设备驱动程序之间的接口是device数据结构。其中定义了网络设备驱动程序需要实现的函数集, 如open、 stop、hard_start_xmit等。各种网络设备的device结构中都要对这个函数集的实现。TCP/IP协议利用这组函数真正完成网络数据的发送和接收。】

调用流程:socket -> sys_socketcall->sys_socket–> inet_create
在这里插入图片描述

为一个INET BSD socket绑定一个地址:

  1. bind() 函数,利用sys_bind()系统调用(应用层)
  2. sys_bind()系统调用根据 socket 的文件描述符 fd,找到它对应的 file、inode、socket 数据结构。将 socket 地址从用户空间拷贝到内核。(表示层 BSD socket,已经进入内核)
  3. 在BSD socket层执行 sock->ops->bind (),因此,bind 的主要工作在 INET socket 层完成,并需要底层的 TCP 和 UDP 协议层提
    供一些支持。一个已经绑定了地址的 socket 不能再用于其它通讯。(会话层 INET socket 层)
  4. INET socket 层完成 bind 工作的函数是 inet_bind()
    【UDP 和 TCP 都维护一个 hash table,用于查找进来的 IP 信息的地址,从而把它们转到正确的 socket/sock 对。UDP 维护一个已分配的 UDP 端口的 hash table:udp_table。TCP 更加复杂,因为它维护了几个 hash table 。 但是,在绑定操作中,TCP 实际上并不把绑定的 sock 数据结构加到它的 hash table 中,它只是检查请求的端口当前没有被使用。在 listen 操作中, sock 数据结构才加到 TCP 的 hash table 中。】
    调用流程:bind ->sys_socketcall-> sys_bind -> inet_bind

在INET BSD socket上监听

  1. listen() 函数,利用sys_listen()系统调用(应用层)
  2. sys_listen()系统调用根据 socket 对应文件描述符 fd, 找到该 socket 对应的 file、inode、socket数据结构。调用 socket 协议操作集上的 listen 函数完成真正的 listen 工作。(表示层 BSD socket,已经进入内核)
  3. 在BSD socket层执行 sock->ops->listen ()。所以真正的 listen 在协议操作集中完成。 INET 提供的 listen 函数是 inet_listen。(会话层 INET socket 层)
  4. inet_listen()中将sock状态设置为TCP_LISTEN
    【对于 UDP socket, 改变 socket 的状态已经足够, 但是 TCP 要把 socket 的 sock 数据结构加到它的两个 hash table 中, 原因是该 socket 已经激活。这两个 hash 表分别是tcp_bound_hash 和 tcp_listening_hash 表。这两个表都通过一个基于 IP 端口号的 hash函数进行索引。】
    调用流程:listen -> sys_socketcall-> sys_listen -> inet_listen

Connection to an INET BSD Socket

  1. connect() 函数,利用sys_connect()系统调用(应用层)
  2. sys_connect()系统调用根据 socket 对应文件描述符 fd, 找到该 socket 对应的 file、inode、socket数据结构。将地址 uservaddr 由用户空间拷贝到内核空间。调用 socket 操作集上的 connect 函数完成真正的连接工作。(表示层 BSD socket,已经进入内核)
  3. 在BSD socket层执行socket操作集上的connect函数。不同的协议族对 connect 函数的实现是不同的。inet_connect () (会话层 INET socket 层)
    4.调用 sock 操作集中的 tcp_connect函数。(下层传输层函数)
    【在connect中可以看到三次握手时,状态的变化。客户端自动绑定端口也是发生在connect函数中(inet_connect)】
    connect -> sys_socketcall -> sys_connect -> inet_connect -> tcp_connect

Accepting Connection Requests

  1. accept() 函数,利用sys_accept()系统调用(应用层)
  2. sys_accept()系统调用根据 socket 对应文件描述符 fd, 找到该 socket 对应的 file、inode、socket数据结构。申请一个新的 socket(inode)。 新 socket 的类型(type)等于老 socket 的类型。调用 socket 操作集中的 dup 函数, 复制一个 socket。 INET 中完成该操作的函数是 sock_no_dup,实际是调用协议集的 create 函数重新创建一个 socket。调用新 socket 操作集中的 accept 操作。(表示层 BSD socket,已经进入内核)
  3. 在BSD socket层执行socket操作集上的accept函数。INET 对该函数有两个实现:inet_accept和 sock_no_accept,前者用于 stream 类型,后者用于 dgram 类型。(会话层 INET socket 层)
    4.调用 sock 操作集中的 accept函数。TCP 中完成 accept 动作的函数是 tcp_accept(下层传输层函数)
    【sys_accept 在调用 inet_accpet 函数之前已经使用 inet_dup 函数创建了其对应的 sock 结构,newsock 的data字段已经指向了其对应的 sock 结构。inet_dup 调用 inet_create,创建了和原来的 sock 结构,协议,类型一致的 sock 结构。该 inet_connect 内部又将调用下层函数tcp_accept】
    accept -> sys_socketcall -> sys_accpet -> inet_accpet -> tcp_accept(TCP是tcp_accept)
    在这里插入图片描述
    参考:
    【1】https://blog.csdn.net/wenqian1991/article/details/46546477
    【2】Linux内核分析第十一章
    【3】Linux 2.0.x 源码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bilidi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值