1.1.操作系统

物理内存和虚拟内存

 

博客

虚拟内存与物理内存的联系和区别:虚拟内存与物理内存的联系与区别_TLpigff的博客-CSDN博客

虚拟内存与物理内存的区别:虚拟内存与物理内存的区别,_虚拟内存csdn_汪汪富贵的博客-CSDN博客

物理内存与虚拟内存:https://www.cnblogs.com/xingmuxin/p/10978414.html

为什么出现虚拟内存?

在没有虚拟内存的概念时,程序寻址用的都是物理地址,在32位的平台下,寻址范围就是2^32大小,也就是4G。如果没有虚拟内存,每次开启一个进程都需要4G内存,会出现以下问题:

    • 当内存较小时,不能同时运行多个进程,只能等一个进程运行完了,再将其他进程装进内存,频繁的装入移除内存效率极低。
    • 由于指令都是直接访问物理内存的,那么一个进程可能会错误修改其他进程的数据,设置修改内核地址空间的数据,极其危险。
    • 因为内存是随机分配的,所以程序运行的地址也是不对的。

虚拟内存

每个进程都会得到4G内存,但是只是进程这样认为,对于物理内存而言,一个进程使用多少,才会分配多少空间。虚拟内存中进程认为得到的是一个连续的空间,而在物理内存中通常被分割为多个物理内存碎片,甚至一部分存储在外部磁盘上,需要的时候进行数据交换。

进程访问地址的过程

  • 进程访问前,需要把访问地址翻译为实际物理内存地址。
  • 所以进程共享一整块物理内存,每个进程只把需要的虚拟地址映射到物理内存上。
  • 进程需要知道那个地址空间上的数据在物理内存中以及具体地址,哪些不在内存(在磁盘、

上),这就需要通过页表来记录。

  • 页表的每一个表项分为两部分,第一部分记录此页是否在物理内存上,(如果在)第二部分

记录物理内存页的地址。

  • 当进程访问某个虚拟地址的时候,就会先去看页表,如果发现对应的数据不再物理内存上,

就会发生缺页操作。虚拟空间映射到磁盘空间,通过mmap技术,mmap是用来建立虚拟空间和磁盘空间的映射关系的。

  • 缺页异常发生后,操作系统会立即阻塞该进程,并将磁盘上的对应的页置换入内存,然后使

该进程就绪,如果内存满了,就需要根据操作系统的内存页置换算法决定如何置换了。

虚拟内存与物理内存的映射关系

缓存IO和直接IO

1.缓存IO和直接IO的区别:缓存IO和直接IO_Drogon Brother的博客-CSDN博客

缓存IO与直接IO:缓存IO和直接IO_Drogon Brother的博客-CSDN博客

调度算法

博客

常见的作业调度算法:缓存IO和直接IO_Drogon Brother的博客-CSDN博客

大厂面试最爱问的【调度算法】,20张图一举拿下:大厂面试爱问的「调度算法」,20 张图一举拿下

CPU在进程间调度算法

CPU调度算法:CPU调度算法总结_处理器调度算法_Rock_N_Roll_的博客-CSDN博客

CPU调度算法:CPU调度算法 - 简书

  • 先来先服务调度算法,
  • 最短作业优先调度算法,
  • 高响应比优先调度算法,
  • 时间片轮转调度算法,
  • 最高优先级调度算法,
  • 多级反馈队列调度算法。

内存页面置换算法

操作系统原理(二)——内存管理值页面置换算法:https://www.cnblogs.com/schips/p/10920145.html

内存管理值页面置换算法:内存管理之页面置换算法_aging算法_csdn_dwk的博客-CSDN博客

  • 最佳页面置换算法(OPT),
  • 先进先出置换算法(FIFO),
  • 最近最久未使用置换算法(LRU),
  • 时钟页面置换算法(Clock),
  • 最不常用置换算法(LFU)。

磁盘调度算法

四种常见磁盘调度算法:四种常用磁盘调度算法_磁盘调度算法有哪几种,各自的特点是什么_杰哥一号号的博客-CSDN博客

磁盘调度算法:磁盘调度算法_zper的博客-CSDN博客

  • 先来先服务算法,
  • 最短寻道时间算法,
  • 扫描算法,
  • 循环扫描算法,
  • LOOK算法与C-LOOK算法。

死锁

博客

死锁面试题(什么是死锁,产生死锁的原因及必要条件):

死锁面试题(什么是死锁,产生死锁的原因及必要条件)_AddoilDan的博客-CSDN博客

概念:

指多个线程在运行过程中因争夺资源而造成的一种僵局,若无外力作用,它们都将无法继续向前推进。

产生死锁的原因:

竞争资源

进程间推进顺序非法。

死锁产生的必要条件:

互斥条件:进程要求对所分配的资源进行排他性控制,即在一段时间内某资源仅为一个进程所持有。

占有且等待条件:当进程因请求资源而阻塞时,对它已获得的资源保持不放。

不可抢占条件:进程已经获取的资源在未使用完之前,不能剥夺,只能在使用完后由自己释放。

循环等待条件:在发生死锁时,必然存在一个进程——资源的环形链。

解决死锁的基本方法:

预防死锁:破坏死锁的必要条件。(互斥条件)不可破坏;(占有且等待)一次性申请所有资源,这样就不需要等待了;(不可抢占)占有部分资源的线程进一步申请其他线程时,如果申请不到,可以主动释放它占有的资源;(循环等待)按照指定次序依次申请资源。

避免死锁:银行家算法。

检测死锁:可以为每个进程和每个资源指定一个唯一的号码;然后建立资源分配表和进程等待表。

解除死锁:剥夺资源,从其他进程剥夺足够的资源给死锁进程,以解除死锁状态;可以直接撤销死锁进程或撤销代价最小的进程,直至有足够的资源可用或者死锁状态解除。

线程与进程

进程、线程之间关系与区别

1.多线程与多进程的区别:多进程和多线程的区别是什么​?-常见问题-PHP中文网

2.进程和线程基础知识全家桶,30张图一套带走:进程和线程基础知识全家桶,30 张图一套带走

并发和并行的概念区分:https://www.cnblogs.com/fanguangdexiaoyuer/p/10834737.html

进程

1.进程类型:

独立进程:如果一个进程不能影响其他进程或被其他进程所影响,那么该进程为独立进程。

协作进程:如果一个进程能影响其他进程或被其他进程所影响,那么该进程为协作进程。

2.进程间通信的方式:

共享内存:在共享内存模式下,建立起一块供协作进程共享的内存区域,进程可以通过向此共享区域读或写入数据来完成信息交换。

消息传递:在信息传递模式中,通过在协作进程间交换信息来实现通信。

3.客户机——服务器间的系统通信:

Socket:Socket由IP地址和端口号连接组成,采用客户机——服务器结构,服务器通过监听指定端口来等待客户请求,一但接收到客户请求,服务器就接收来自客户Socket的连接,从而完成连接。(服务器实现的特定服务是通过监听众所周知的端口号来实现的,Telnet服务器监听端口23,Ftp服务器监听端口21,Web或Http服务器监听端口80。)

RPC(remote process call,远程过程调用)

RMI(remote method invocation,远程方法调用)

线程

1.多线程的优点:

响应度高:采用多线程实现的交互程序,及时其部分阻塞或执行较冗长的操作,该程序仍能继续执行,从而增加了对用户的响应程度。

资源共享:线程默认共享它们所属进程的内存和资源。

经济:进程创建所需要的内存和资源的分配比较昂贵,由于线程能共享它们所属进程的资源,所以创建和切换线程会更为经济。

多处理器体系结构的利用:能够充分使用多处理器体系结构,以便每个进程能并行运行在不同的处理器上。

2.多线程模型:线程类别和分为用户层的用户线程和内核层的内核线程,用户线程受内核线程支持,而无须内核管理;而内核线程由操作系统直接支持和管理。

多对一模型:将许多用户级线程映射到一个内核线程。线程管理由线程库在用户空间进行,因而效率较高。但是如果一个线程执行了阻塞系统调用,那么整个进程会阻塞。而且,因为任意时刻只能有一个线程能访问内核,多个线程不能并行运行在多处理器上。

一对一模型:将每个用户线程映射到一个内核线程,该模型在一个线程执行阻塞系统调用时,能允许另一个线程的执行,所以它提供了比多对一模型更好的并发功能,并且允许多个线程运行在多处理器系统上。缺点是没创建一个用户线程就需要创建一个相应的内核线程,由于创建内核线程的开销会影响应用程序的性能,所以这种模型的绝大多数实现限制了系统所支持的线程数量。

多对多模型:多路复用了许多用户线程到同样数量或更小数量的内核线程上,内核线程的数量可能与特定应用程序或特定机器有关。虽然多对一允许开发人员创建任意多的用户线程,但是因为内核一次只能调度一个线程,所以并没有增加并发性。多对多模型解决了多对一和一对一两个模型的缺点,即允许开发人员创建任意多的用户线程,并且相应内核线程能在多处理器系统上并发执行,而且,当一个线程执行阻塞系统调用时,内核能调度另外一个线程来执行。

3.线程库(当前所使用的主要线程库):

POSIX Pthread、Win32、Java。

4.系统调用fork()和exec()

如果程序中的一个线程调用fork,Unix系统存在两种实现形式,一种为新进程会复制父进程的所有线程,一种是只复制调用系统fork()的线程。

而对于exec()函数,系统调用exec()后,那么exec()参数所指定的程序会替换整个进程,包括所有线程。

fork()的两种形式的使用与应用程序有关,如果调用fork()之后立即调用exec(),那么没有必要复制所有线程,因为exec()参数所指定的程序会替换整个进程,在这种情况下,只复制调用线程比较适当;如果,调用fork()函数之后不调用exec(),那么另一进程应该复制所有线程。

5.线程取消:指在线程完成之前提前终止线程的操作。

目标线程可在如下两种情况下发生:

异步取消:一个线程立即终止目标线程

延迟取消:目标线程不断的检查它是否应终止,这允许目标线程以以有序方式来终止自己。

6.信号处理

线程状态(包含六种和五种两个版本)

1.线程六种状态分别有哪些?

慕课网-程序员的梦工厂

初始(new)->运行(runnable)->阻塞(blocked)->等待(waiting)->等待超时(time waiting)->终止(terminated)

2.线程的5种状态详解:

线程的5种状态详解_线程有哪几种状态_老猫1226的博客-CSDN博客

初始(new)->就绪(runnable)->running(运行)->阻塞(blocked)->终止(terminated)

阻塞状态分三种情况:

①等待阻塞:运行的线程执行到wait()方法时,该线程会释放占用的所有资源,JVM会将该线程放入等待池中,进入这个状态后,线程时不能自动唤醒的,必须依赖外部调用notify()或者notifyAlll()方法才能唤醒。

②同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其他线程占用,jvm会把线程放入锁池中。

③其他阻塞:运行的线程执行sleep或者join方法,或者发出了io请求,JVM会把线程置为阻塞状态,当sleep超时,join等待线程终止或者超时,或者IO处理完毕时,线程重新转入就绪状态。

线程(进程)间通信与同步机制

博客:

1.进程/线程同步的方式和机制,进程间通信:

https://www.cnblogs.com/virusolf/p/5331946.html

2.进程间通信和线程间通信的几种方式:

https://www.cnblogs.com/fanguangdexiaoyuer/p/10834737.html

线程的同步机制:

互斥量

信号量

条件变量

进程同步机制:

1.互斥锁:用于实现线程间对资源互斥访问的机制,有两种状态,开锁和关锁。当一个线程需要操作一个共享数据时,首先判断mutex的状态,当mutex状态为开锁时,线程为该数据段执行关锁命令,则访问该资源的其他线程将被阻塞,执行完后,释放该锁;当mutex状态为关锁时,阻塞等待。

2.条件变量:只利用mutex来实现互斥访问可能会引起互斥锁。每个条件变量都与一个互斥锁一起使用,在创建一个互斥锁时便联系了一个条件变量。单纯的互斥锁用于短期锁定,主要保证临界区的互斥进入,条件变量用于线程的长期等待,直至等待的资源成为可用的资源。

3.信号量机制:允许多个线程在同一时刻访问同一资源,但是需要限制最大线程数据。信号量允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。

信号量S是一个整数,S>=0时代表可供并发进程使用的资源实体数,S

PV操作概括如下,P操作申请资源,

S-1;若S-1>=0,进程继续执行;若S-1

V操作释放资源,

S+1;若S+1>0,进程继续执行;若S+1

信号量可分为,私用信号量,当某线程需要利用信号量来实现同一进程间的各线程同步时,可调用创建信号量的命令来创建私用信号量;

公用信号量:公用信号量是为实现不同进程间或不同进程间各线程的同步而设定。

4.事件:通过通知的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作。

进程间通信方式:

1.管道:管道分为有名管道和无名管道。无名管道只能用于亲属进程间通信,有名管道则可用于无亲属关系进程之间通信。

2.消息队列:就是一个消息的链表,是一系列保存在内核中的消息的列表。

3.信号量:信号量是一个计数器,信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

4.信号:操作系统中,不同信号用不同的值表示,每个信号设置相应的函数,一旦进程发送某一个信号给另一个进程,另一进程将执行响应的函数进行处理。也就是说先把可能出现的异常等问题准备好,一旦信号产生就执行相应的逻辑即可。

5.共享内存:共享内存允许两个或多个进程共享一个指定的存储区,存储区的地址可以被两个或多个进程映射至自己的存储区。

6.SOCKET:套接字不同于其他进程间通讯的方式,它不仅可以应用于同一机器上的不同进程间通信,也可以应用于不同机器上的进程间通信。

线程间通信方式(线程间通信的目的主要用于线程同步,没有像进程通信中的用于数据交换的通信机制):

锁机制:包括互斥锁、条件变量、读写锁

信号量机制:包括无名线程信号量和命名线程信号量

信号机制:类似进程间的信号处理

IPC(inter-process communication)

Linux操作系统的用户态与内核态

1.博客

Linux探秘之用户态与内核态:

https://www.cnblogs.com/bakari/p/5520860.html

怎样去理解用户态和内核态:

怎样去理解Linux用户态和内核态? - 知乎

2.原理:

①定义:

内核态:控制计算机的硬件资源,例如协调CPU,分配内存资源,并且提供稳定的环境工应用程序运行。

用户态:提供应用程序运行的空间。

②用户态访问内核态资源的三种方式:

系统调用:调用操作系统的最小功能单位。不同的Linux发行版本提供的系统调用数量不尽相同,大概在240~350个之间。

库函数:屏蔽底层复杂实现,对系统调用的封装,提供给程序员调用系统资源的入口。

Shell:对内核封装后提供的应用程序,通过shell脚本可实现用户对系统资源的调用。

③用户态到内核态切换的三种方式:

系统调用:

异常:运行在用户态的应用程序,发生异常事件会触发切换至内核态,例如缺页异常。

外设中断:外设完成用户请求后,会向CPU发送中断信号。

缓存一致性协议

1.博客:

CPU缓存一致性协议MESI:

https://www.cnblogs.com/yanlong300/p/8986041.html

2.概念

①MSI协议:是一个在多处理器系统中运行的基本的监听高速缓存一致性协议。(MSI,Modified、Shared、Invalid,分别表示高速缓存块中的当前状态修改、共享和无效)

②MESI协议:是支持回写高速缓存的最常用协议之一并且基于Invalidate的高速缓存一致性协议。(MESI,Modified、Exclusive、Shared、Invalid分别表示修改、独享、共享和无效)

IO模型(阻塞/非阻塞,异/同步)

博客

AIO简介:AIO 简介_庚庚911的博客-CSDN博客

面试之多路复用:面试之多路复用_coolgw2015的博客-CSDN博客

java aio和nio的区别:java aio和nio的区别_这瓜保熟么的博客-CSDN博客

100%弄明白5种IO模型:100%弄明白5种IO模型 - 知乎

IO多路复用机制详解:Netty教程-IO多路复用机制详解 - 简书

IO多路复用到底是不是异步的?IO多路复用到底是不是异步的? - 知乎

Java NIO:浅析IO模型:https://www.cnblogs.com/dolphin0520/p/3916526.html

TCP发送数据的流程:

以两个应用程序通讯为例,我们来了解一下当A向B发送一条消息,简单来说会经过如下流程:

  1. 应用A把消息发送到TCP缓冲区。
  2. TCP发送缓冲区再把消息发送出去,经过网络传递后,消息会发送到B服务器的TCP接受缓冲区。
  3. B再从TCP缓冲区去读取属于自己的数据。

有这样一个问题,因为应用之间发送消息是间断性的,也就是说上图中的TCP缓冲区还没有接受到属于应用B该读取的消息时,那么此时应用B向TCP缓冲区发起读取申请,TCP缓冲区是应该马上告诉应用B现在没有你的数据,还是说让应用B在这里等待,直到有数据再把数据交给应用B。当然,应用到调用方也是一样的,如果应用A在向TCP缓冲区发送数据时,如果TCP缓冲区已经满了,那么是告诉应用A这里没空间了,还是让应用A等待,直到TCP发送缓冲区有空间了再把应用A的数据拷贝到发送缓冲区。

分类

  • 同步IO、异步IO、阻塞IO、非阻塞IO
  • Unix网络编程中的五种IO模型:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO、异步IO
  • BIO、NIO、AIO

1.阻塞IO

当然,上面的问题就简述了什么是阻塞IO,什么是非阻塞IO。阻塞IO就是当应用B发起读缓冲区申请时,在内核还没有准备好数据之前,应用B会一直处于等待数据状态,知道内核把数据准备好了拷贝到应用B才结束。

术语解释:在应用调用recvfrom读取数据时,其系统调用直到数据包到达且被赋值到应用缓冲区中或者发送错误数据时才返回,在此期间一直会等待,进程从发起系统调用阻塞至收到返回值,这种模型成为阻塞模型。

流程:应用进程向内核发起recfrom读取数据;内核准备数据报,应用进程被阻塞;将数据从内核复制到应用空间;复制成功后,返回成功提示。

2.非阻塞IO

按照上面问题的思路,非阻塞IO就是当应用B发起读取数据申请时,如果内核数据没有准备好就会即刻告诉应用B,不会阻塞B在这里等待。

术语解释:非阻塞IO是在应用调用recvfrom从内核读取数据时,如果内核缓冲区没有数据的话,就会直接返回一个EWOULDBLOCK错误,不会让应用一直等待中。在没有数据的时候会即刻返回错误标识,那也意味着如果应用想要读取数据就要不断的调用recvfrom请求,知道读取到它想要的数据为止。

流程:应用进程向内核发起recvfrom读取数据;内核没有数据准备好,就会立刻返回EWOULDBLOCK错误码;应用进程再次向内核发起recvfrom读取数据;已有数据包准备好久进行下一步骤,否则还是返回EWOULDBLOCK错误码;如果内核有数据放回,就会将数据从内核空间拷贝至用户空间;完成后,返回成功提示。

3.IO多路复用模型

有这样一个问题,我们还是关注应用B从TCP缓冲区中读取数据这个环节。如果在并发的环境下,可能会有N个人向应用B发送消息,这门情况下我们的应用就必须创建多个线程来读取数据,每个线程都会自己调用recvfrom去读取数据,那么情况将会是以下这种情况。

如上图一样,并发情况下服务器可能一瞬间会收到几十上百万的请求,这种情况下应用B就需要创建几十上百万的线程去读取数据,此外,应用线程是不知道什么时候会有数据可以读取,为了保证消息能及时收到,就需要这些线程自己不断的向内核发送recvfrom请求来读取数据。

那么问题来了,这么多的线程不断调用recvfrom请求数据,先不说服务器能不能承受这个么多的线程,就算扛得住,很明显这种方式也太浪费资源了,线程是我们操作系统的宝贵资源,大量的线程用来去读取数据,那么就意味着能多其他事情的线程就会很少。

所以有人提出一种思路,能不能提供一种方式,可以由一个线程监控多个网络请求(后面我们称为文件描述符,linux系统把所有网络请求都以一个fd来标识),这样就可以只需要一个或几个线程就可以完成数据状态询问的操作了,当有数据准备就绪之后再分配对应的线程去读取数据,这么做就可以节省出大量的线程资源出来,这个就是IO多路复用模型的思想。

正如上图,IO复用模型的思路就是系统提供了一种函数可以同时监控多个fd的操作,这个函数就是我们常说的select,poll,epoll函数,有了这个函数后,应用线程通过调用select函数就可以同时监听多个fd,select函数监控的fd只要有任何一个数据准备就绪了,select函数就会返回可读状态,这时询问线程再去通知处理数据的线程,对应线程此时再发起recvfrom请求去读取数据了。

术语描述:进程通过将一个或多个fd传递给select,阻塞在select操作上,select帮我们侦测多个fd是否准备就绪,select返回数据可读状态,应用程序再创建线程调用recvfrom读取数据。

总结:多路复用IO模型的基本思路就是通过select或poll、epoll来监控多fd,来达到不必为每一个fd创建一个对应的监控线程,从而减少线程资源创建的目的。

4.异步IO

通过观察我们发现,不管非阻塞模型还是IO多路复用模型,我们要读取一个数据都是要发起两阶段的请求,第一次发送请求询问是否准备好,第二次请求发送recvfrom请求读取数据。

于是,就产生了这样一种方案,应用只需要向内核发起一次read请求,告诉内核它要读什么数据后即刻返回。内核收到请求后就会建立一个信号联系,当数据准备就绪,内核就会主动把数据从内核空间复制到用户空间,等所有操作都完成之后,内核就会发起一个通知告诉应用,我们称这种一劳永逸的模型为异步IO模型。

属于描述:应用告知内核启动某个操作,并让内核在真正操作完成之后,通知应用。在异步IO的模式下,应用不再需要先后发送询问请求,接受数据请求两个操作,而是只需要向内核发送一次请求就可以完成状态询问和数据拷贝的所有操作。

5.信号驱动IO

BIO,NIO,AIO

NIO == 多路复用

多路复用方式

博客

浅析epoll的水平触发和边缘触发,以及边缘触发为什么要使用非阻塞IO:浅析epoll的水平触发和边缘触发,以及边缘触发为什么要使用非阻塞IO_epoll为什么可以边缘触发_虚心学习进步的博客-CSDN博客

Linux IO模式及select,poll,epoll详解:Linux IO模式及 select、poll、epoll详解 - 人云思云 - SegmentFault 思否

彻底搞懂epoll高效运行的原理:

百度安全验证

IO多路复用模型(Select、Poll、Epoll):IO多路复用模型(Select、Poll、Epoll )_epoll反射模型_Jaemon的博客-CSDN博客

I/O模型以及多路复用三种实现方式select、poll和epoll比较与区别:

I/O模型以及多路复用三种实现方式select、poll和epoll比较及区别_火锅技术栈的博客-CSDN博客

IO多路复用之epoll模型:

IO多路复用之epoll模型_Black.Spider的博客-CSDN博客

select

各个客户端连接的文件描述符也就是套接字,都被放到一个集合中,调用select函数之后会一直监视这些文件描述符中有哪些可读,如果有可读的额描述符那么我们的工作线程就去读取资源。我们在select函数中告诉内核需要监听的不同状态的文件描述符以及能接受的超时时间,函数会返回所有状态下就绪的描述符的个数,并且可以通过遍历fdset,来找到就绪的文件描述符。

存在的问题:

    • 每次调用select,都需要把待监控的fd集合从用户空间拷贝到内核空间,当fd很大时,开

销很大。

    • 每次调用select,都需要轮训一遍所有的fd,查看就绪状态。这个开销在fd比较多时开销

很大。

    • select支持的最大文件描述符数量有限,默认是1024。

poll

poll和select的实现非常类似,本质上的区别就是存放fd集合的数据结构不一样,select在一个进程内可以维持最多1024个连接,poll在此基础上做个加强,可以维持任意数量的连接。

但poll和select方式有一个很大问题就是,select和poll都需要轮训所有的文件描述符才能确定哪些文件描述符有读写就绪请求,对于无就绪请求的文件描述符的轮训,势必造成大量的资源浪费。

epoll

epoll维护的文件描述符数目不再受限制,而且性能不会随着文件描述符的增加而下降。

epoll先通过一个epoll_ctl注册到一个文件描述符到内核中,并一直维护着而不像poll每次操作都需要将所有要监控的文件描述符传递给内核;在描述符读写就绪时,通过回调函数将自己加入到就绪队列中,之后epoll_wait返回该就绪队列。也就是说epoll基本不做无用的操作,时间复杂度仅与活跃的客户端数有关,而不会随着文件描述符数据的增加而下降。

epoll在内核空间通过一个红黑树的结构维护着监听的所有文件描述符,当某个文件描述符读写事件就绪时,就通过回调机制将自己加入到就绪的事件队列中,当应用程序调用epoll_wait时,就可以将就绪的事件队列拷贝到用户态返回给应用程序。

epoll在传递内核与用户空间的消息时使用了共享内存,而不是内存拷贝,这也使得epoll的效率比poll和select高。

  • 水平触发(Level Trrigger)

默认采用LT模式,当epoll_wait检测到描述符事件发生并将此事件通知应用程序时,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。

  • 边缘触发(Edge Trigger)

一种高速的工作方式,当epoll_wait检测到文件描述符事件发生并将该事件通知应用程序时,应用程序应该立即处理该事件,否则,下次调用epoll_wait将不再通知该事件。

下面是epoll的总体运行结构描述:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值