当前位置: 首页 > news >正文

深入理解Linux网络(四):TCP接收阻塞

TCP socket 接收函数 recv 发出 recvfrom 系统调用。
进⼊系统调⽤后,⽤户进程就进⼊到了内核态,通过执⾏⼀系列的内核协议层函数,然后到 socket 对象的接收队列中查看是否有数据,没有的话就把⾃⼰添加到 socket 对应的等待队列⾥。最后让出CPU,操作系统会选择下⼀个就绪状态的进程来执⾏。
在这里插入图片描述
假如我们没有使⽤ O_NONBLOCK 标记,等待接收的过程会阻塞进程,但是我们先探究阻塞的过程。

//file: net/socket.c
SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t,size, unsigned int, flags, struct sockaddr __user *, addr,int __user *, addr_len)
{struct socket *sock;//根据⽤户传⼊的 fd 找到 socket 对象sock = sockfd_lookup_light(fd, &err, &fput_needed);......err = sock_recvmsg(sock, &msg, size, flags);......
}

sock_recvmsg -> __sock_recvmsg -> __sock_recvmsg_nosec

static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,struct msghdr *msg, size_t size, int flags)
{......return sock->ops->recvmsg(iocb, sock, msg, size, flags);
}

在之前的 socket 对象图中,从图中看到 recvmsg 指向的是 inet_recvmsg 方法。
在这里插入图片描述

//file: net/ipv4/af_inet.c
int inet_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags)
{...err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT,flags & ~MSG_DONTWAIT, &addr_len);

这里又出现了一个 recvmsg 函数指针,不过这个是socket 对象中的 recvmsg 方法,对应 TCP 协议的 tcp_recvmsg 方法。

//file: net/ipv4/tcp.c
int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,size_t len, int nonblock, int flags, int *addr_len)
{int copied = 0;...do {//遍历接收队列接收数据skb_queue_walk(&sk->sk_receive_queue, skb) {...}...}if (copied >= target) {release_sock(sk);lock_sock(sk);} else //没有收到⾜够数据,启⽤ sk_wait_data 阻塞当前进程sk_wait_data(sk, &timeo);
}

可以看到,消息量不够,一样也会阻塞。
在这里插入图片描述
如果没有收到数据,或者收到不⾜够多,则调⽤ sk_wait_data 把当前进程阻塞掉。

//file: net/core/sock.c
int sk_wait_data(struct sock *sk, long *timeo)
{//当前进程(current)关联到所定义的等待队列项上DEFINE_WAIT(wait);// 调⽤ sk_sleep 获取 sock 对象下的 wait// 并准备挂起,将进程状态设置为可打断 INTERRUPTIBLEprepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);// 通过调⽤schedule_timeout让出CPU,然后进⾏睡眠rc = sk_wait_event(sk, timeo, !skb_queue_empty(&sk->sk_receive_queue));...

sk_wait_data 阻塞进程的实现:
在这里插入图片描述
做完排队工作后,给所在进程改个状态位即可。
⾸先在 DEFINE_WAIT 宏下,定义了⼀个等待队列项 wait。 在这个新的等待队列项上,注册了回调函数 autoremove_wake_function,并把当前进程描述符 current 关联到其 .private 成员上。

//file: include/linux/wait.h
#define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, autoremove_wake_function)
#define DEFINE_WAIT_FUNC(name, function) \wait_queue_t name = { \.private = current, \.func = function, \.task_list = LIST_HEAD_INIT((name).task_list), \}

紧接着在 sk_wait_data 中 调⽤ sk_sleep 获取 sock 对象下的等待队列列表头 wait_queue_head_t。
sk_sleep 源代码如下:

//file: include/net/sock.h
static inline wait_queue_head_t *sk_sleep(struct sock *sk)
{BUILD_BUG_ON(offsetof(struct socket_wq, wait) != 0);return &rcu_dereference_raw(sk->sk_wq)->wait;
}

接着调⽤ prepare_to_wait 来把新定义的等待队列项 wait 插⼊到 sock 对象的等待队下。

//file: kernel/wait.c
void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
{unsigned long flags;wait->flags &= ~WQ_FLAG_EXCLUSIVE;spin_lock_irqsave(&q->lock, flags);if (list_empty(&wait->task_list))__add_wait_queue(q, wait);set_current_state(state);spin_unlock_irqrestore(&q->lock, flags);
}

这样后⾯当内核收完数据产⽣就绪时间的时候,就可以查找 socket 等待队列上的等待项,进⽽就可以找到回调函数和在等待该 socket 就绪事件的进程了。
最后再调⽤ sk_wait_event 让出 CPU,进程将进⼊睡眠状态,这会导致⼀次进程上下⽂的开销。

相关文章:

深入理解Linux网络(四):TCP接收阻塞

TCP socket 接收函数 recv 发出 recvfrom 系统调用。 进⼊系统调⽤后,⽤户进程就进⼊到了内核态,通过执⾏⼀系列的内核协议层函数,然后到 socket 对象的接收队列中查看是否有数据,没有的话就把⾃⼰添加到 socket 对应的等待队列⾥…...

【iOS】内存五大分区

目录 堆(Heap)是什么五大分区栈区堆区全局/静态区常量区(即.rodata)代码区(.text) 函数栈堆和栈的区别和联系图解 OC语言是C语言的超集,所以先了解C语言的内存模型的内存管理会有很大帮助。C语言…...

Jupyter Notebook: 是一个强大的交互式计算

文章目录 引言Jupyter Notebook的原理基础使用安装与启动单元格(Cell)操作快捷键 高级使用魔术命令Markdown支持可视化版本控制 优缺点优点缺点 官网链接结论 引言 Jupyter Notebook是一个强大的交互式计算环境,特别适用于数据科学、机器学习…...

【C#学习笔记】变量、变量类型

在C#中,变量是存储数据的容器,每个变量都有其特定的数据类型,这决定了变量可以存储的数据类型和大小。以下是关于C#中变量的由浅入深的详细解释,并附带代码示例和解释: 基础概念 定义: 变量是存储数据的容…...

题解:T480718 eating

eating 题目背景 从前有个荣光的王国,小 A 是里面的国王,今天他要赐予他的子民以仓廪。 题目描述 在一条街上有 n n n 个饭店。小 A 站在这条街的最左端。 第 i i i 个饭店离这条街最左端的距离是 a i a_i ai​,它所售卖的菜品的美味…...

MATLAB中matfile用法

目录 语法 说明 示例 创建 MAT 文件对象 启用对 MAT 文件的写访问权限 加载整个变量 将整个变量保存至现有 MAT 文件 加载和保存部分变量 确定变量大小 参数说明 局限性 提示 matfile的功能是访问和更改 MAT 文件中的变量,而不必将文件加载到内存中。 …...

Spring之Spring Bean的生命周期

Spring Bean的生命周期 通过BeanDefinition获取bean的定义信息调用构造函数实例化beanBean的依赖注入处理Aware接口(BeanNameAware、BeanFactoryAware、ApplicationContextAware)Bean的后置处理器BeanPostProcessor-前置初始化方法(Initiali…...

OSINT 开源情报中的地理定位方法

了解 OSINT 中的地理定位技术、如何获取地理位置数据以及如何将地理定位用于各种调查场景。 OSINT 中的地理定位基础知识 OSINT 代表开源情报,指的是从免费公共来源合法收集的有关个人或组织的信息。这包括在互联网上以及书籍、公共图书馆报告、报纸文章、新闻稿、…...

Java面试题系列 - 第17天

Java中的代理模式与动态代理 背景说明:代理模式是一种结构型设计模式,用于在客户端和目标对象之间提供一个代理或占位符。在Java中,动态代理技术允许在运行时创建代理对象,这在AOP(面向切面编程)和RPC&…...

开发环境搭建

1、Ubuntu 系统设置 root 用户密码 新安装的ubuntu没有设置 root 用户密码,打开终端,输入 sudo passwd root 执行命令后依次输入密码 2、虚拟机设置网络适配器 3、Ubuntu 系统下搭建 FTP 服务器 sudo apt-get update sudo apt-get install vsftpd sudo apt-get install vim…...

【NLP】关于参数do_sample的解释

在自然语言处理(NLP)领域,特别是在使用神经网络模型进行文本生成时,do_sample是一个常见的参数,用于控制模型生成文本的方式。具体来说,do_sample参数决定模型是否采用随机采样(sampling&#x…...

Vbox虚拟机+Ubuntu motest测试drm

1. 效果演示 大家做学习drm的时候,没有硬件测试平台不方便测试,这里给大家演示下如何基于Vbox虚拟机Ubuntu测试drm的一些功能,先看下演示视频。 没有光标测试: demo_vwmfgx_test_drm 带有光标测试: demo_vwmfgx_drm_with_cursor 可以看到,有…...

ArcGIS Pro SDK (九)几何 15 转换

ArcGIS Pro SDK (九)几何 15 转换 文章目录 ArcGIS Pro SDK (九)几何 15 转换1 创建地理转换2 创建复合地理变换3 创建投影转换4 创建高压基准变换5 创建复合高压基准变换6 决定转换7 地图点 - 地理坐标字符串转换 环境&#xff1…...

Spring IOC DI --- 认识IOC DI

T04BF 👋专栏: 算法|JAVA|MySQL|C语言 🫵 今天你敲代码了吗 文章目录 认识Ioc & DIIoc是什么?DI是什么? 认识Ioc & DI 我们知道,Spring 是一个开源框架,让我们的开发更加简单.但是更加具体来说,实际上Spring 是包含了众多工具方法的Ioc容器 …...

常用的python程序汇总——入门级

只用于记录最近的一些日常程序。 目录 前言 一、文件和目录管理 1.读取文件结构 读取所有文件夹和文件 读取到N级子文件夹和文件 只读取到N级子文件夹 2.遍历文件并处理(复制、删除) 说明: 二、数据分析和处理 三、数据可视化 四、…...

被问到MQ消息已丢失,该如何处理?

在分布式系统中,消息中间件(如 RabbitMQ、RocketMQ、Kafka、Pulsar 等)扮演着关键角色,用于解耦生产者和消费者,并确保数据传输的可靠性和顺序性。尽管我们通常会采取多种措施来防止消息丢失,如消息持久化、…...

open3d:ransac分割多个平面(源码)

1、背景介绍 随机采样一致性算法(RANSAC Random Sample Consensus)是一种迭代的参数估计算法,主要用于从包含大量噪声数据的样本中估计模型参数。其核心思想是通过随机采样和模型验证来找到数据中最符合模型假设的点。因此,只要事先给定要提取的参数模型,即可从点云中分割…...

Github 2024-07-17 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-07-17统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量非开发语言项目3Python项目3Rust项目2TypeScript项目2MDX项目1项目化学习 创建周期:2538 天协议类型:MIT LicenseStar数量:161973 个Fork数量…...

vue3中Composition API写法 <script setup>标签中哪些可以不用导入即可使用?

在 Vue 3 中使用 <script setup> 时&#xff0c;确实有一些全局的 API 和宏可以直接使用&#xff0c;而不需要显式地从 vue 包中导入它们。这是因为 <script setup> 是专门为了提供更简洁的组件编写方式而设计的&#xff0c;它内部利用了编译时的语法糖。 以下是在…...

Facebook Dating:社交平台的约会新体验

随着社交媒体的普及和技术的发展&#xff0c;传统的社交方式正在经历革新&#xff0c;尤其是在约会这个领域。Facebook作为全球领先的社交平台&#xff0c;推出了Facebook Dating&#xff0c;旨在为用户提供一个全新的约会体验。本文将探讨Facebook Dating如何重新定义社交平台…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...