图解通用网络IO底层原理、Socket、epoll、用户态内核态······

LInux 操作系统中断

什么是系统中断

这个没啥可说的,大家都知道;

CPU 在执行任务途中接收到中断请求,需要保存现场后去处理中断请求!保存现场称为中断处理程序!处理中断请求也就是唤醒对应的任务进程来持有CPU进行需要的操作!

有了中断之后,提升了操作系统的性能!可以异步并行处理很多任务!

  • 软中断(80中断)

由CPU产生的;CPU检查到程序代码段发生异常会切换到内核态;

  • 硬中断

由硬件设备发起的中断称为硬中断!可以发生在任何时间;比方说网卡设备接收到一组报文;对应的报文会被DMA设备进行拷贝到网卡缓冲区!然后网卡就会向CPU发起中断信号(IRQ):

CPU收到信号后就会执行网卡对应的中断处理程序!

内核在系统中断时做了什么事

每种中断都有它对应的中断处理程序;

对应到内核的某一个代码段;

CPU接收到中断后;首先需要将寄存器中数据保存到进程描述符!PCB!

随后切换到内核态处理中断处理程序!执行网卡的程序;

执行完毕之后切换到用户态,根据PCB内容恢复现场!然后就可继续执行代码段了!

硬件中断触发的过程

中断请求寄存器: 保存需要发送中断请求的设备记录!

优先级解析器:中断请求是有优先级之分的,因为CPU不能同时执行多个中断请求!

正在服务寄存器:正在执行的请求!比方我正在打字,这里面记录的就是键盘IRQ1 !

操作系统启动时需要将硬件向量值与处理程序地址进行映射!当硬件发送中断信息时只会发送向量值,通过匹配找到对应的处理程序!

Socket基础

Socket读写缓冲区机制

所谓socket,在底层也无非就是一个对象,通过对象绑定两个缓冲区,也就是数据队列,然后调用系统API对这两个缓冲区的数据进行操作罢了!

发数据;用户态转内核态,将数据拷贝到send缓存区,然后调用write系统调用将数据拷贝到网卡,再由网卡通过TCP/IP协议进行数据包的网络发送!

socket两种工作模式

  • BIO

总结:读数据读不到就一直等,发数据发不了就一直等!

  • NIO

读数据读不到就等一会再读,取数据取不到就等一会再取!

接受端缓冲区打满了,线程又抢占不到CPU去清理缓冲区,怎么办!

最后发送端的数据缓冲区也会被打满!

系统调用;用户态------内核态

  • 系统调用:

int 0X80对应的就是系统调用中断处理程序;向量值为128;system_call;


IRQ是有限的,不可能为每一个系统调用都分配一个向量值,所以统一使用80中断来进行系统调用的路由!

相关视频推荐

linux内核《epoll源码分析》

epoll实战揭秘-支撑亿级IO的底层基石

剖析Linux内核《中断管理技术栈》

学习地址:c/c++ linux服务器开发 /后台架构师

需要C/C++ Linux服务器架构师学习资料加qun579733396获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

为什么要有这两种状态

指令的危险程度不一样;

对于不同的指令,为了保证系统安全,划分了用户空间和内核空间;

linux中:0表示内核态,3表示用户态!

所以:linux在创建进程的时候就会为进程分配两块空间;

用户栈:分配变量,创建对象

内核栈:分配变量!

什么时候进程进行切换至内核态

硬中断;

用户态中代码出现错误也要切换!

进程切换时都做了什么

CPU中存在很多寄存器

这些寄存器保存了进程在进行运算时的一些瞬时数据;如果现在要进行进程切换了;这些数据都需要找个地方保存起来;那么保存到哪里呢?

进程PCB:在OS创建进程的时候同时也会分配一段空间存放进程的一些信息;其中就有一个字段指向一个数据结构;叫做进程控制块PCB:

用来描述和控制进程的运行的一个数据结构——进程控制块PCB(Process Control Block),是进程实体的一部分,是操作系统中最重要的记录型数据结构。

  • PCB是进程存在的唯一标志

  • 系统能且只能通过PCB对进程进行控制和调度

  • PCB记录了操作系统所需的、用于描述进程的当前情况以及控制进程运行的全部信息

所以:在进程进行切换的时候CPU中的数据保存到了PCB中,供CPU回来时读取恢复!

Linux select 多路复用函数

select就是一个函数:只要传入相应的参数就能获得相应的数据:

1、们所关心的文件描述符fd;

2、描述符中我们关心的状态:读事件、写事件、等

3、等待时间

调用结束后内核会返回相关信息给我们!

做好准备的个数

哪些已经做好准备;有了这些返回信息,我们就可以调用合适的IO函数!这些函数就不会再被阻塞了;-

函数详解

int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, timeval *timeout)- maxfdp1 readset 和 wirteset中的最大有数据位
- readset  bitmap结构的位信息;保存我们需要读取的socket序号;
- writeset 写数据信息
- exceptset 异常信息

select函数这里不再细讲,可以翻看以前的文章

将函数需要的参数准备好之后调用select;

select进行80中断;将rset数据拷贝到内核中;查询对应的状态之后设置rset对应的位置值,

完成后又拷贝到用户态中的rset;这样一来rset里面的位信息就代表了哪些socket是准备好了的!

随后遍历这些位信息就可以调用read或wirte进行缓冲区的操作了!

缺点

可以看到,while死循环中每次执行都将rset重新置位;然后循环重新SET位信息;随后才会发起请求!过程较为繁琐且重复!

select多路复用器底层原理分析

epoll函数

了解到select的缺点后发现:select每次得到数据都要进行复位,然后又进行重复的步骤去内核中获取信息;感觉就是很多时间都花在重复的劳动上,为了解决这个问题,linux在2.6引入epoll模型,单独在内核区域开辟一块空间来做select主动去做的事,select是主动查,epoll则是准备数据,线程来了直接取就行了;大大提升了性能

既然是函数,看看相关的函数实现:

实现思路:

在内核创建一块空间;总所周知;linux下一切皆文件;所以所谓创建的空间也就是一个文件描述符fd,然后这个文件结构中有两个指针指向另外两个地址空间:事件队列、就绪队列

事件队列:存放已经建立所有socket连接

就绪队列:准备就绪的socket;也就是read或write的时候不用阻塞的socket;

其实epoll就像一个数据库;里面有两个数据表;一个放连接列表;一个放准备就绪的连接列表;

既然有这两个队列;就要涉及到增删查;这就是另外两个函数的来由;

创建epoll空间
int epoll_create(int size);int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

对事件队列进行增删改:

epfd : epoll的文件描述符号:因为内核中可能有多个epoll

op : 参数op有以下几个值: EPOLL_CTL_ADD:注册新的fd到epfd中,并关联事件event; EPOLL_CTL_MOD:修改已经注册的fd的监听事件; EPOLL_CTL_DEL:从epfd中移除fd,并且忽略掉绑定的event,这时event可以为null;

fd : 表示socket对应的文件描述符。

epoll底层原理解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/344065.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv10开源,高效轻量实时端到端目标检测新标准,速度提升46%

前言 实时目标检测在自动驾驶、机器人导航、物体追踪等领域应用广泛,近年来,YOLO 系列模型凭借其高效的性能和实时性,成为了该领域的主流方法。但传统的 YOLO 模型通常采用非极大值抑制 (NMS) 进行后处理,这会增加推理延迟&#…

gulimall-search P125 springboot整合elasticsearch版本冲突

一、问题 spring-boot.version 2.2.4.RELEASE,在gulimall-search pom.xml中添加elasticsearch.version 7.4.2后,发现出现如下问题:elasticsearch版本是springboot引入的6.8.6,没有变为7.4.2。 二、原因 在gulimall-search 的pom文件中&#…

【数据结构】平衡二叉树左旋右旋与红黑树

平衡二叉树左旋右旋与红黑树 平衡二叉树 定义 平衡二叉树是二叉搜索树的一种特殊形式。二叉搜索树(Binary Search Tree,BST)是一种具有以下性质的二叉树: 对于树中的每个节点,其左子树中的所有节点都小于该节点的值…

Python - 深度学习系列38 重塑实体识别5-预测并行化改造

说明 在重塑实体识别4中梳理了数据流,然后我发现pipeline的串行效率太低了,所以做了并行化改造。里面还是有不少坑的,记录一下。 内容 1 pipeline 官方的pipeline看起来的确是比较好用的,主要是实现了比较好的数据预处理。因为…

党史馆3d网上展馆

在数字化浪潮的推动下,华锐视点运用实时互动三维引擎技术,为用户带来前所未有的场景搭建体验。那就是领先于同行业的线上三维云展编辑平台搭建编辑器,具有零基础、低门槛、低成本等特点,让您轻松在数字化世界中搭建真实世界的仿真…

【SpringBoot】SpringBoot整合RabbitMQ消息中间件,实现延迟队列和死信队列

📝个人主页:哈__ 期待您的关注 目录 一、🔥死信队列 RabbitMQ的工作模式 死信队列的工作模式 二、🍉RabbitMQ相关的安装 三、🍎SpringBoot引入RabbitMQ 1.引入依赖 2.创建队列和交换器 2.1 变量声明 2.2 创建…

Python实现半双工的实时通信SSE(Server-Sent Events)

Python实现半双工的实时通信SSE(Server-Sent Events) 1 简介 实现实时通信一般有WebSocket、Socket.IO和SSE(Server-Sent Events)三种方法。WebSocket和Socket.IO是全双工的实时双向通信技术,适合用于聊天和会话等&a…

SwiftUI中Mask修饰符的理解与使用

Mask是一种用于控制图形元素可见性的图形技术&#xff0c;使用给定视图的alpha通道掩码该视图。在SwiftUI中&#xff0c;它类似于创建一个只显示视图的特定部分的模板。 Mask修饰符的定义&#xff1a; func mask<Mask>(alignment: Alignment .center,ViewBuilder _ ma…

AI论文速读 | 2024[KDD]GinAR—变量缺失端到端多元时序预测

题目&#xff1a;GinAR: An End-To-End Multivariate Time Series Forecasting Model Suitable for Variable Missing 作者&#xff1a;Chengqing Yu&#xff08;余澄庆&#xff09;, Fei Wang&#xff08;王飞&#xff09;, Zezhi Shao&#xff08;邵泽志&#xff09;, Tangw…

XML解析库tinyxml2库使用详解

XML语法规则介绍及总结-CSDN博客 TinyXML-2 是一个简单轻量级的 C XML 解析库,它提供了一种快速、高效地解析 XML 文档的方式。 1. 下载地址 Gitee 极速下载/tinyxml2 2. 基本用法 下面将详细介绍 TinyXML-2 的主要使用方法: 2.1. 引入头文件和命名空间 #i…

Docker 国内镜像源更换

实现 替换docker 镜像源 前提要求 安装 docker docker-compose 参考创建一键更换docker国内源 vim /docker_daemon.sh #!/bin/bash # -*- coding: utf-8 -*- # Author: make.han # Email: CIASM@CIASM # Date: 2024/06/07 # docker daemon.jsondaemon_json_file="/et…

js 选择一个音频文件,绘制音频的波形,从右向左逐渐前进。

选择一个音频文件&#xff0c;绘制波形&#xff0c;从右向左逐渐前进。 完整代码&#xff1a; <template><div><input type"file" change"handleFileChange" accept"audio/*" /><button click"stopPlayback" :…

大模型微调工具LLaMA-Factory docker安装、大模型lora微调训练

参考: https://github.com/hiyouga/LLaMA-Factory 报错解决: 1)Docker 构建报错 RuntimeError: can’t start new thread: https://github.com/hiyouga/LLaMA-Factory/issues/3859 修改后的Dockerfile: FROM nvcr.io/nvidia/pytorch:24.01-py3WORKDIR /appCOPY require…

el-input中change事件造成的坑

el-input中change事件造成的坑 一、change事件定义二、如果仅回车时候触发 一、change事件定义 仅在输入框失去焦点或用户按下回车时触发 二、如果仅回车时候触发 <el-inputv-model.trim"questionInput"placeholder"请输入你的问题&#xff0c;按回车发送&…

NDIS Filter开发-PNP响应和安装

NDIS filter驱动可能是最容易生成的驱动之一&#xff0c;如果你安装了VS 2015 WDK之后&#xff0c;你可以直接生成一个能运行的Filter驱动&#xff0c;它一般是ndislwf。 和大部分硬件不同&#xff0c;NDIS Filter驱动介于软件和硬件抽象层之上&#xff0c;它和硬件相关&…

2024年最新的软件测试面试总结(答案+文档)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 测试技术面试题 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 参考答案&#xff1a; 兼容测试主要是检查软件在不同的硬件平台、软件平…

老师如何制作高考后志愿填报信息采集系统?

高考结束后&#xff0c;志愿填报成为学生们的头等大事。面对众多选择&#xff0c;如何高效、准确地填报志愿&#xff0c;是每个学生和家长都关心的问题。作为老师&#xff0c;能否利用现有的技术工具&#xff0c;帮助学生更好地完成志愿填报呢&#xff1f; 老师们需要一个能够…

[C#]使用OpenCvSharp图像滤波中值滤波均值滤波高通滤波双边滤波锐化滤波自定义滤波

在使用OpenCvSharp进行图像滤波处理时&#xff0c;各种滤波方法都有其特定的用途和效果。以下是对中值滤波、均值滤波、高通滤波、双边滤波、锐化滤波和自定义滤波的详细解释和归纳&#xff1a; 中值滤波&#xff08;MedianBlur&#xff09; 原理与作用&#xff1a;中值滤波是…

SpringBoot实现参数校验拦截(采用AOP方式)

一、AOP是什么&#xff1f; 目的&#xff1a;分离横切关注点&#xff08;如日志记录、事务管理&#xff09;与核心业务逻辑。 优势&#xff1a;提高代码的可读性和可维护性。 关键概念 切面&#xff08;Aspect&#xff09;&#xff1a;包含横切关注点代码的模块。通知&#xff…

leetcode-04-[24]两两交换链表中的节点[19]删除链表的倒数第N个节点[160]相交链表[142]环形链表II

一、[24]两两交换链表中的节点 重点&#xff1a;暂存节点 class Solution {public ListNode swapPairs(ListNode head) {ListNode dummyHeadnew ListNode(-1);dummyHead.nexthead;ListNode predummyHead;//重点&#xff1a;存节点while(pre.next!null&&pre.next.next…