图解通用网络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.mzph.cn/web/23908.shtml

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

相关文章

《大宅门》特别活动走进李良济,开启探寻中医药文化之旅!

《大宅门》话剧将于6月14-16日在苏州湾大剧院上演,为了让大家了解到中医药知识,6月2日,李良济携手苏州湾大剧院举办《大宅门》特别活动“探寻中医药文化之旅”! 6月2日下午,大家一起走进李良济,深度了解传统…

vite热更新导致的问题及解决

一、封装axios拦截器后,每次热更新虽然请求了一次,但是response了多次: import axios from "axios"; axios.interceptors.request.use() axios.service.interceptors.response.use()导致此问题是因为触发了多次拦截器,相当于是给axios添加了多个拦截器,所以多次…

怎么能通过chatgpt-on-wechat获取全部的微信聊天信息

要通过 chatgpt-on-wechat 工具获取全部的微信聊天信息,你可以按照以下步骤操作: 安装并配置 itchat 库: itchat 是一个开源的微信个人号接口,可以帮助你获取微信群聊信息。 pip install itchat登录微信: 使用 itchat …

小白必学!场外期权的交易模式

场外期权的交易模式 随着金融市场的深化与创新,场外期权交易作为一种灵活多样的金融衍生品交易方式,正逐渐成为投资者关注的焦点。场外期权,顾名思义,是在非交易所市场进行的期权交易,与交易所期权有着显著的区别。那…

Promed Bioscience—高纯度胶原蛋白

Promed Bioscience——高纯度胶原蛋白供应商 专于研发,忠于质量,创新驱动 AXXORA 作为Enzo life sciences公司的子公司,是欧美最大的生命科学研究信息、服务、销售电子一站式服务平台之一,AXXORA精选欧洲四十多家优秀的生命科学研…

Mac 使用Docker安装Elasticsearch、Kibana 、ik分词器、head

安装ElasticSearch 通过docker安装es docker pull elasticsearch:7.8.1 在本地创建elasticsearch.yml文件 mkdir /Users/ky/Documents/learn/es/elasticsearch.yml 编辑yml文件内容 http: host: 0.0.0.0 xpack.security.enabled: false xpack.security.enrollment.enabled: t…

JAVA-LeetCode 热题-第24题:两两交换链表中的节点

思路: 定义三个指针,其中一个临时指针,进行交换两个节点的值,重新给临时指针赋值,移动链表 class Solution {public ListNode swapPairs(ListNode head) {ListNode pre new ListNode(0,head);ListNode temp pre;wh…

docker部署fastdfs

我的镜像包地址 链接:https://pan.baidu.com/s/1j5E5O1xdyQVfJhsOevXvYg?pwdhcav 提取码:hcav docker load -i gofast.tar.gz拉取gofast docker pull sjqzhang/go-fastdfs启动gofast docker run -d --name fastdfs -p 8080:8080 -v /opt/lijia/lijia…

antd vue a-select 搜索

数据结构 list: [{ name: "序号", id: 0, show: true },{ name: "出库单编号", id: 1, show: false },{ name: "wbs元素", id: 2, show: true },{ name: "序号1", id: 3, show: true },{ name: "出库单编号1", id: 4, show…

Java_Collection的其它相关知识

前置知识:可变参数 就是一种特殊形参,定义在方法,构造器的形参列表里,格式是:数据类型…参数名称; 可变参数的好处和特点 好处:常常用来接受数据。 特点:可以不传数据给它&#xf…

如何从小米手机传输文件到电脑? [5个简单的方法]

与苹果设备间的AirDrop或iTunes等工具相比,Android手机到PC的文件传输似乎不那么便捷。但小米用户有多种应用,如Mi PC Suite和ShareMe,可以高效地进行传输。本文将介绍5种将小米设备文件传输到PC的方法,包括使用和不使用USB线的情…

深度学习_02_卷积神经网络循环神经网络

卷积神经网络 1. 卷积神经网络 神经元存在局部感受区域----感受野 . 第一个卷积神经网络雏形----新认知机 缺点:没有反向传播算法更新权值,模型性能有限 第一个大规模商用卷积神经网络----Lenet-5 缺点:没有大量数据和高性能计算资源。 第一个…

图解 React diff 算法

Render 阶段会生成 Fiber Tree,所谓的 diff 实际上就是发生在这个阶段,这里的 diff 指的是 current FiberNode 和 JSX 对象之间进行对比,然后生成新的的 wip FiberNode。 除了 React 以外,其他使用到了虚拟 DOM 的前端框架也会有类…

C++的枚举

文章目录 简介枚举的基本语法基本使用方法习题简介 在C++中,枚举(Enumeration)是一种数据类型,它允许程序员定义一个变量并指定它可以取的那些固定值的集合。枚举的主要目的是提高代码的可读性和维护性,通过使用有意义的名称而不是数字来表示状态、类型或其他固定集合的值…

Kafka之Producer原理

1. 生产者发送消息源码分析 public class SimpleProducer {public static void main(String[] args) {Properties prosnew Properties();pros.put("bootstrap.servers","192.168.8.144:9092,192.168.8.145:9092,192.168.8.146:9092"); // pros.pu…

OceanBase v4.2 特性解析:Lateral Derived Table 优化查询

前言 从传统规则来看,内联视图通常不允许引用在同一FROM子句中前面定义的表的列。但从OceanBase 4.2.2版本开始,这一限制得到了突破,允许内联视图作为Lateral Derived Table来定义,从而允许此类引用。Lateral Derived Table的语法…

26-LINUX--I/O复用-select

一.I/O复用概述 /O复用使得多个程序能够同时监听多个文件描述符,对提高程序的性能有很大帮助。以下情况适用于I/O复用技术: ◼ TCP 服务器同时要处理监听套接字和连接套接字。 ◼ 服务器要同时处理 TCP 请求和 UDP 请求。 ◼ 程序要同时处理多个套接…

Facebook广告素材如何测试?手把手教你!

广告素材对Facebook广告效果的影响是很大的,用对了素材,Facebook广告的价值就越高。广告主们通常会先通过广告测试,根据数据反馈来挑选素材。今天就手把手教你做Facebook素材测试的技巧,让你更有灵感和思路! 创意测试 …

Hudi CLI 安装配置总结

前言 上篇文章 总结了Spark SQL Rollback, Hudi CLI 也能实现 Rollback,本文总结下 Hudi CLI 安装配置以及遇到的问题。 官方文档 https://hudi.apache.org/cn/docs/cli/ 版本 Hudi 0.13.0(发现有bug)、(然后升级)0.14.1Spark 3.2.3打包 mvn clean package -DskipTes…

使用 Django 构建动态网页

文章目录 创建 Django 项目和应用程序创建 HTML 模板创建视图函数配置 URL 路由运行 Django 服务器使用 Django 模板语言 Django 是一个流行的 Python Web 框架,它能够帮助开发人员快速构建强大的 Web 应用程序。在 Django 中,HTML 是用于呈现网页内容的…