内蒙古网站建设,网页版微信二维码不出来,做网站几天,深圳东门买衣服攻略1 用户空间和内核空间以Centos 7 linux操作系统为例。计算机系统被内核操控#xff0c; 内核被应用操控。为了避免用户应用导致冲突甚至内核崩溃#xff0c;用户应用与内核是分离的进程的寻址空间会划分为两部分:内核空间、用户空间。用户空间只能执行受限的命令(Rin3#x…1 用户空间和内核空间以Centos 7 linux操作系统为例。计算机系统被内核操控 内核被应用操控。为了避免用户应用导致冲突甚至内核崩溃用户应用与内核是分离的进程的寻址空间会划分为两部分:内核空间、用户空间。用户空间只能执行受限的命令(Rin3最低级命令)而且不能直接调用系统资源必须通过内核提供的接口来访问内核可以选择暴露哪些资源可以被用户访问。内核空间可以执行特权命令 (Ring0可以直接访问系统资源)调用一切系统资源以32位CPU为例其内存空间为2的32次方即4GB将其分为内核空间和用户空间如下图所示Linux系统为了提高IO效率会在用户空间和内核空间加入缓冲区在写数据时要把用户的缓冲数据拷贝到内核缓冲区然后写入到磁盘。注意图中红箭头写数据图在读数据时要从设备读取数据到内核缓冲区然后拷贝到用户缓冲区。注意图中黑色箭头用户向内核发起读数据的指令如果数据还没到达则需要等待数据数据从网络中传输到磁盘然后读取到内核态的缓冲区用户太将数据从内核缓冲区copy到自己的缓冲区。读数据图影响性能的点1、在读取数据时会发生阻塞2、用户态和内核态缓冲区的拷贝会影响效率。2 网络模型2.1 阻塞IO(Blocking IO)用户获取数据的过程图的左半部分是应用的等待过程右半部分是等待过程中内核做哪些内核等待磁盘准备数据内核将数据拷贝到用户太的缓存中。可以看到阻塞IO模型中用户进程在两个阶段都是阻塞状态。2.2 非阻塞IO NonBlocking IO用户获取数据的过程左半部分用户一直在循环尝试获取锁数据右图部分内核在等待数据然后将数据拷贝到用户空间中。在第一阶段内核直接返回失败信息。在第二阶段数据拷贝时用户需要阻塞。可以看到非阻塞10模型中用户进程在第一个阶段是非阻塞第二个阶段是阻塞状态。虽然是非阻塞但性能并没有得到提高。而且忙等机制会导致CPU空转CPU使用率暴增。2.3 IO多路复用无论是阻塞IO还是非阻塞IO用户应用在一阶段都需要调用recvfrom函数差别在于无数据时的处理如果调用recvfrom时恰好没有数据阻塞10会使进程阻塞非阻塞10使CPU空转都不能充分发挥CPU的作用。如果调用recvfrom时恰好有数据则用户进程可以直接进入第二阶段读取并处理数据。在阻塞IO的情况下服务端处理客户端Socket请求时在单线程的情况下只能处理一个socket如果正常处理的socket数据还没有准备就绪线程就会被阻塞其他客户端的socket都必须等待性能很差。提高效率的方法1、开启多线程同时处理多个socket。2、不排队当谁数据准备好了cpu就去处理谁。那么内核如何知道哪些socket数据已经准备就绪了呢可以通过文件描述符知道!!!文件描述符(File Descriptor)文件描述符: 简称FD是一个从0开始递增的无符号整数用来关联Linux中的一个文件。在Linux一切皆文件例如常规文件、视频、硬件设备等当然也包括网络套接字 (Socket)。 IO多路复用 :是利用单个线程来同时监听多个FD并在某个FD可读、可写时得到通知从而避免无效的等待充分利用CPU资源。用户进程调用select函数监听多个sockets然后内核态告知用户态哪些sockets的数据已经准备就绪然后用户态调用recvfrom函数获取数据。监听FD的方式、通知的方式又有多种实现selectpollepoll差异:select和poll只会通知用户进程有FD就绪但不确定具体是哪个FD需要用户进程逐个遍历FD来确认epoll则会在通知用户进程FD就绪的同时把已就绪的FD写入用户空间。综合对比epoll更占优势。2.4 Selectselect是Linux中最早的I/0多路复用实现方案例如select 监督读事件的fd集合。1.1 创建fd_set集合1.2 监听fd 1,2,51.3 切换到内核态并将fd_set拷贝然后执行select函数2.1内核遍历集合2.2查看准备就绪的fd没有则休眠2.3 等待数据就绪被唤醒或者超时。2.4 将fd_set拷贝到用户态的中。select模式存在的问题:需要将整个fd_set从用户空间拷贝到内核空间select结束还要再次拷贝回用户空间select无法得知具体是哪个fd就绪需要遍历整个fd_setfd_set监听的fd数量不能超过1024。2.5 Pollpoll模式对select模式做了简单改进但性能提升不明显部分关键代码如下IO流程创建pollfd数组向其中添加关注的fd信息数组大小自定义调用poll函数将pollfd数组拷贝到内核空间转链表存储无上限内核遍历fd判断是否就绪数据就绪或超时后拷贝pollfd数组到用户空间返回就绪fd数量n用户进程判断n是否大于0大于0则遍历pollfd数组找到就绪的fd与select对比select模式中的fd set大小固定为1024而pollfd在内核中采用链表理论上无上限监听FD越多每次遍历消耗时间也越久性能反而会下降2.5 epollepoll模式是对select和poll的改进它提供了三个函数epoll_create在内核中创建eventpoll结构体返回对应的句柄epfdepoll_ctl将fd加入到红黑树上如果数据准备就绪触发callback将其加入到就绪的list链表中epoll_wait检查rdlist列表是否为空不为空则返回就绪的FD数量。epoll流程图select模式存在的三个问题能监听的FD最大不超过1024每次select都需要把所有要监听的FD都拷贝到内核空间每次都要遍历所有FD来判断就绪状态poll模式的问题:poll利用链表解决了select中监听FD上限的问题但依然要遍历所有FD如果监听较多性能会下降epoll模式中如何解决这些问题的?基于epoll实例中的红黑树保存要监听的FD理论上无上限而且增删改查效率都非常高性能不会随监听的FD数量增多而下降。每个FD只需要执行一次epoll_ctl添加到红黑树以后每次epol wait无需传递任何参数无需重复拷贝FD到内核空间内核会将就绪的FD直接拷贝到用户空间的指定位置用户进程无需遍历所省FD就能知道就绪的FD是谁2.6 信号驱动IO信号驱动IO是与内核建立SIGIO的信号关联并设置回调当内核有FD就绪就会通知用户期间用户可以执行其他业务。当有大量I0操作时信号较多SIGIO处理函数不能及时处理可能导致信号队列溢出而且内核空间与用户空间的频繁信号交互性能也较低。2.7 异步IO闲的闲死累的累死。同步和异步的区分看第二阶段是阻塞还是非阻塞的。3 Redis网络模型Redis到底是单线程还是多线程如果仅考虑Redis的核心业务部分命令处理答案是单线程如果考虑整个Redis那么答案是多线程。在Redis 6.0 核心网络模型引入了多线程。为什么Redis作者选择单线程抛开持久化不谈Redis是纯内存操作执行速度非常快它的性能瓶颈是网络延迟而不是执行速度因此多线程并不会带来巨大的性能提升。多线程会导致过多的上下文切换带来不必要的开销引入多线程会面临线程安全问题必然要引入线程锁这样的安全手段实现复杂度增高而且性能也会大打折扣3.1 单线程下的网络模型Redis通过10多路复用来提高网络性能并且支持各种不同的多路复用实现并且将这些实现进行封装提供了统一的高性能事件库API库AE:源码server.c