深入理解Linux网络(三):TCP对象创建

深入理解Linux网络(三):TCP对象创建

TCP对象创建

常见的三句TCP编程:

int main()
{
 int sk = socket(AF_INET, SOCK_STREAM, 0);
 connect(sk, ...)
 recv(sk, ...)
}

简单的两三⾏代码,但实际上⽤户进程和内核配合做了⾮常多的⼯作。
首先⽤户进程发起创建 socket 的指令,然后切换到内核态完成了内核对象的初始化。
接着在数据包的接收上,是硬中断和 ksoftirqd 进程在进⾏处理。
当 ksoftirqd 进程处理完以后,再通知到相关的⽤户进程。
从创建 socket,到⽹络包抵达⽹卡到被接收,流程如下:
在这里插入图片描述
数据结构间的调用如下:
在这里插入图片描述

//file:net/socket.c
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
 ......
 retval = sock_create(family, type, protocol, &sock);
}

sock_create 继续调用 __sock_create:

//file:net/socket.c
int __sock_create(struct net *net, int family, int type, int protocol,
 struct socket **res, int kern)
{
 struct socket *sock;
 const struct net_proto_family *pf;
 ......
 //分配 socket 对象
 sock = sock_alloc();
 //获得每个协议族的操作表
 pf = rcu_dereference(net_families[family]);
 //调⽤每个协议族的创建函数, 对于 AF_INET 对应的是
 err = pf->create(net, sock, protocol, kern);
}

net_proto_family->create 会调用 inet_create:

//file:net/ipv4/af_inet.c
static int inet_create(struct net *net, struct socket *sock, int protocol, int kern)
{
 struct sock *sk;
 //查找对应的协议,对于TCP SOCK_STREAM 就是获取到了
 //static struct inet_protosw inetsw_array[] =
 //{
 // {
 // .type = SOCK_STREAM,
 // .protocol = IPPROTO_TCP,
 // .prot = &tcp_prot,
 // .ops = &inet_stream_ops,
 // .no_check = 0,
 // .flags = INET_PROTOSW_PERMANENT |
 // INET_PROTOSW_ICSK,
 // },
 //}
 list_for_each_entry_rcu(answer, &inetsw[sock->type], list)
 {
  //将 inet_stream_ops 赋到 socket->ops 上
  sock->ops = answer->ops;
  //获得 tcp_prot
  answer_prot = answer->prot;
  //(1)分配 sock 对象, 并把 tcp_prot 赋到 sock->sk_prot 上
  sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot);
  //(2)对 sock 对象进⾏初始化
  sock_init_data(sock, sk);
 }
}

针对上面的代码:

inet_create

inet_create 中根据类型 SOCK_STREAM 查找到对于 tcp 定义的操作⽅法实现集合 inet_stream_ops 和 tcp_prot。并把它们分别设置到 socket->ops 和 sock->sk_prot 上。
在这里插入图片描述

sock_init_data

sock_init_data 中将 sock 中的 sk_data_ready 函数指针进⾏了初始化,设置为默认 sock_def_readable()。
在这里插入图片描述

//file: net/core/sock.c
void sock_init_data(struct socket *sock, struct sock *sk)
{
 sk->sk_data_ready = sock_def_readable;
 sk->sk_write_space = sock_def_write_space;
 sk->sk_error_report = sock_def_error_report;
}

当软中断上收到数据包时会通过调⽤ sk_data_ready 函数指针(实际被设置成了 sock_def_readable()) 来唤醒在 sock 上等待的进程。
⾄此,⼀个 tcp对象( AF_INET 协议族下 SOCK_STREAM对象)就算是创建完成了。
这⾥花费了⼀次 socket 系统调⽤的开销。

相关推荐

  1. 深入理解Linux网络总结

    2024-07-21 22:10:04       29 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 22:10:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 22:10:04       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 22:10:04       58 阅读
  4. Python语言-面向对象

    2024-07-21 22:10:04       69 阅读

热门阅读

  1. Spring WebFlux 介绍与效果演示示例

    2024-07-21 22:10:04       24 阅读
  2. django 需要修改的文件

    2024-07-21 22:10:04       25 阅读
  3. Random,ThreadLocalRandom,SecureRandom有什么区别

    2024-07-21 22:10:04       21 阅读
  4. Python 爬虫技术 第05节 异常处理

    2024-07-21 22:10:04       24 阅读
  5. 微信小程序开发:DOM 相关 API 使用详解

    2024-07-21 22:10:04       20 阅读
  6. QtQuick-QML语法

    2024-07-21 22:10:04       22 阅读
  7. Codeforces Round 960 (Div. 2)VP

    2024-07-21 22:10:04       23 阅读
  8. WebAssembly在前端开发中的创新与应用

    2024-07-21 22:10:04       20 阅读
  9. easyExcel

    easyExcel

    2024-07-21 22:10:04      21 阅读
  10. 什么是等保测评

    2024-07-21 22:10:04       20 阅读
  11. acml可用订阅到起始位姿

    2024-07-21 22:10:04       22 阅读
  12. Windows 12 网页版

    2024-07-21 22:10:04       20 阅读
  13. 网络融合的艺术:Xcode中应用Web服务集成全指南

    2024-07-21 22:10:04       23 阅读
  14. 提示工程的技术与策略分类

    2024-07-21 22:10:04       21 阅读
  15. css font 优化

    2024-07-21 22:10:04       22 阅读