计算机组成和IO

文章目录

    • 计组和Epoll:
      • 计算机组成原理:
      • 网络数据接收的流程:
      • 内核如何管理socket以及状态的更新
      • select系统调用的复杂度
      • epoll的et和lt模式及java的选择

国内访问chatai就可以

https://aiweb.douguguo.com/?type=add

计组和Epoll:

计算机组成原理:

内核、cpu指令集、寄存器、GDT、IDT、PCB、进程状态、内核进程队列、内核进程调度、中断、DMA、系统调用、用户态内核态


1、内核:内核是计算机操作系统的核心,负责管理计算机硬件和软件资源,以及提供各种系统服务。内核通常被分为内核态和用户态两种,内核态拥有最高的特权级,可以直接访问硬件资源和操作系统底层的接口,而用户态只能通过系统调用来访问这些资源和接口。

2、CPU指令集:CPU指令集是CPU执行的指令集合,包括操作数和操作码。不同的CPU架构有不同的指令集,例如x86架构的CPU指令集是x86指令集,ARM架构的CPU指令集是ARM指令集等。

3、寄存器:寄存器是CPU内部的一组存储器,用于临时存储数据和指令。通常有通用寄存器、专用寄存器、标志寄存器等。

4、GDT:全局描述符表(Global Descriptor Table)是用于内存分段和管理的数据结构,存放了实模式和保护模式下的段描述符,它是在操作系统启动时被创建的。

5、IDT:中断描述符表(Interrupt Descriptor Table)是用于管理中断和异常的数据结构,存放了中断和异常处理程序的地址和特权级等信息。

6、PCB:进程控制块(Process Control Block)是操作系统中用于管理进程的数据结构,包含进程的状态、程序计数器、寄存器、内存地址空间、资源使用情况等信息。

7、进程状态:进程可以处于运行、就绪、阻塞等状态。

8、内核进程队列:内核进程队列是操作系统中用于存放进程控制块的队列,不同状态的进程控制块被存放在不同的队列中。

9、内核进程调度:内核进程调度是操作系统中负责控制进程执行顺序的机制,通过将进程从就绪队列移到运行队列,或者从运行队列移到阻塞或就绪队列来实现。

10、中断:中断是指CPU在执行指令过程中响应硬件或软件事件,以便及时处理这些事件。

11、DMA:直接内存访问(Direct Memory Access)是一种独立于CPU的输入输出技术,通过在内存和设备之间直接传输数据,提高了计算机系统的性能。

12、系统调用:系统调用是用户程序通过中断进入内核态执行的函数,用于访问操作系统提供的底层服务,例如文件操作、进程管理、网络通信等。

13、用户态和内核态:用户态指应用程序运行的状态,其对CPU和硬件资源的访问是受限的,只能通过系统调用等方式来访问内核资源。内核态指操作系统内核运行的状态,其对CPU和硬件资源的访问不受限制,可以直接访问硬件资源和系统内部接口。

【我讲了一个精讲IO课程,比较细节的io剖析】

https://zhuanlan.zhihu.com/p/355582245

网络数据接收的流程:

【linux中,数据到达 从网卡、缓冲区、dma、中断、socket、回调函数、状态管理、epoll红黑树,整个流程描述一下】

在Linux中,当网络数据到达时,其整个处理流程包括以下几个步骤:

1. 从网卡接收数据

当数据从网络上到达时,它首先会被网卡接受,通过DMA copied到主内存缓冲区。在这个过程中,网卡会触发一个中断,通知内核有数据到达。

2. 内核缓存处理

内核会将接收到的数据复制到协议栈的接收缓冲区中,并在缓冲区中为数据分配一个数据包(sk_buff)结构。接着,内核会分析数据包,将其解析成相应的协议头和协议数据。

3. 中断处理

当网卡完成对数据的接收并将数据复制到内存中后,内核会处理接收中断。在中断处理程序中,内核会触发网络协议栈中的回调函数,根据数据包的协议类型,将数据包传递给相应的处理函数进行处理。

4. Socket 接口

处理函数将数据包处理后,将结果返回给内核,之后内核会通过sock结构体中的socket信息找到目标socket。然后将完中断状态下的数据拷贝到socket对应的缓存中进行存储【recv queue   缓冲区】。

5. 回调函数处理

内核会调用socket的回调函数来处理接收到的数据,以更新socket的状态【即事件 readable】。回调函数负责把接收到的数据写入接收缓冲区,同时检查是否有等待该socket数据的进程(应用程序),如果有,则唤醒这些进程【BIO,如果读取不到,进程会block状态进入内核的阻塞队列】。

6. 状态管理

内核会使用红黑树结构来维护当前所有的socket状态。当一个socket的接收缓冲区有数据可读时,内核会将该socket的节点插入到红黑树中。反之,当socket的接收缓冲区为空时,则将其节点从红黑树中移除。【不精准;NIO,read不block,立刻返回,如果recv queue;但是,还得循环read,靠的状态识别】
【------select机制怎么实现的】
7. Epoll 监听

当应用程序使用epoll机制监听一个或多个socket时,内核会将监听的socket插入到一个epoll文件描述符的红黑树中。【【当有数据到达时,内核会在红黑树中寻找相应socket的节点,并触发epoll事件通知应用程序进行读取】】。【红黑树的特点:自旋平衡的树;一个系统有5000个连接,但是,当前程序只持有其中1000个】

综上,这个过程经历了网卡接收、内核缓存、中断、Socket接口、回调函数处理、状态管理及Epoll监听等多个阶段,并使用了多种数据结构和回调函数来协同工作,从而最终实现对网络数据的处理和传输。

内核如何管理socket以及状态的更新

内核使用多种数据结构来管理socket,其中比较重要的是文件描述符表、sock结构体以及epoll中使用的红黑树。

文件描述符表是内核中最基本的socket管理机制,它用于记录文件描述符与socket之间的映射关系,方便内核根据文件描述符找到对应的socket。当用户进程创建新的socket时,内核会为其分配一个唯一的文件描述符,并将该文件描述符与socket相关联。在文件描述符表中,每个文件描述符的状态由一个文件描述符表项(file descriptor table entry)来描述,其中包含了socket的相关信息,如socket的状态、套接字选项等。

sock结构体则是内核中用于描述socket状态的主要数据结构,包含了socket的各种关键属性,如socket的类型、协议族信息、套接字选项、接收缓冲区、发送缓冲区、地址信息等等。当用户进程通过文件描述符对socket进行操作时,内核会根据文件描述符找到对应的sock结构体,并在其中记录相应的操作及其参数。这样,当内核收到操作所触发的事件时,就可以根据sock结构体中的信息来处理相应的操作。

对于epoll机制,内核使用红黑树来统一管理每个socket的状态。红黑树是一种自平衡的二叉查找树,用于快速查找指定节点,它将socket作为节点插入到树中,并根据其状态来更新节点在树中的位置。当状态发生变化时,内核会自动将节点从一个位置移动到另一个位置,这样就可以快速地找到对应状态的socket并处理相应的操作了。

除了这些数据结构,内核还会使用一系列事件回调函数来管理socket状态的更新,如sock_readable、sock_writable等等。每当socket状态发生变化时,内核就会调用相应的回调函数,在其中处理相应的事件。

总而言之,内核会使用多种数据结构和回调函数来管理socket状态的更新,以提高其查询和处理效率。

select系统调用的复杂度

使用多路复用器select时,内核是遍历所有的socket集合,通过位图的形式,找出所有有状态的socket,并将它们加入到文件描述符集合中,然后再遍历select传入的socket集合,根据这个集合去查对应的socket状态,以此决定是否对其进行操作。

需要注意的是,select对可读可写的socket是分别进行处理的,这意味着内核在遍历的过程中需要分别查找可读和可写的状态。这种方式虽然在较早的Unix系统中比较有效,但是随着socket数量的增加和网络速度的提高,它的效率会越来越低。

相比之下,使用epoll的方式,则是通过红黑树和事件驱动的方式来管理socket,内核只需要遍历状态发生变化的socket节点,并触发相应的事件即可,这种方式通过避免遍历所有的socket集合,可以提高查询效率,降低CPU负载。因此,目前在高并发网络应用中,epoll已经逐渐取代了select等I/O多路复用机制。

epoll的et和lt模式及java的选择

epoll支持两种模式:Level Triggered(LT)模式和Edge Triggered(ET)模式,这两种模式控制了epoll在什么样的情况下会向用户空间通知IO事件。

LT模式
LT模式中的LT表示Level Triggered,即水平触发模式。在这种模式下,当epoll_wait返回后,如果发现fd上有未处理的事件,那么下一次epoll_wait仍然会返回事件,直到这些事件被处理完。在LT模式中,也可以使用非阻塞IO和epoll边缘触发的方式一起使用。

ET模式
ET模式中ET表示Edge Triggered,即边缘触发模式。在这种模式下,当epoll_wait返回后,如果发现fd上有未处理的事件,那么下一次epoll_wait只会在fd上有新事件时才会返回。对于EPOLLONESHOT事件,ET模式下同样只会返回一次事件,直到重新调用epoll_ctl注册该fd的监听事件。
【【【【【ET相对于LT 优势:epoll wait 次数少/精准;缺点,应用代码要处理干净数据;;
LT,你不必担心
系统调用成本是不是很大
多数会选择ET模式
java中是不是有一个selector.select()方法:
如果给你返回了一个socket可以read
你只读取了一半
下一次selector.select()还能否得到这个socket?
请回答:
有可能读取到,有可能读取不到
为什么?
在使用selector的时候,是不是要自己手动remove掉key!【你知道你会读取完,并且你使用的是NIO 】【如果你就处理的一部分,你就不应该remove它】
在ET模式下,java的多次selector.select(),你又没有remove掉key,为啥每次都给你返回???
因为java选择了epoll的ET模式,它知道这个问题,所以,jvm层面维护了一个集合
所以:最总结论:
java用着ET这种少系统调用的模型,封装出一个LT模型,且在用户空间
】】】】】】】

ET模式监测的事件是相对立即的,所以会比LT模式更加高效

【--纠正--】
Java 在使用 epoll 时,采用的是 ET(Edge Triggered)模式。Java 的 NIO 实现是基于 Linux epoll 机制的,不同于 Unix 传统的 select 和 poll 机制。Java NIO 的 selector 封装了 epoll 的高效 I/O 多路复用接口,只有监听的事件发生了变化,例如套接字的 I/O 可读或可写事件时,才会触发 selector 的 select 操作,并将这个事件拷贝到用户态处理。使用 ET 模式可以减少触发 epoll_wait 的次数,提高系统的效率。但是需要注意的是,使用 ET 模式需要谨慎处理消息读取的问题,以避免遗漏数据的问题。

你可能感兴趣的:(面试,java,IO)