sellect、poll、epoll三者的区别

先来了解一下什么是进程切换

为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行,这种行为为进程的切换,任务切换,或者上下文切换

转载:

http://www.cnblogs.com/alex3714/articles/5876749.html

http://www.cnblogs.com/alex3714/p/4372426.html

https://segmentfault.com/a/1190000003063859

进程切换详细概念

任何进程都是在操作系统内核的支持下运行的,是与内核紧密相关的.

从一个进程的运行转到另一个进程上运行,这个过程经过这些变化

1.保存处理机上下文,包括程序计算器和其他寄存器

2.更新PCB信息 (也就是进程控制块,存放着操作系统用于描述进程情况及控制进程运行所需的全部信息)

3.把PCB信息 移入相应的队列,如就绪,在某件事阻塞等队列

4.选择另一个进程执行,并更新PCB信息

5.更新内存管理的数据结构

6.恢复处理机上下文

所以很消耗资源

进程的阻塞

正在执行的进程,由于期待的某些事件未发生,如请求系统资源失败、等待某种操作的完成、新数据尚未到达或无新工作做等,则由系统自动执行阻塞原语(Block),使自己由运行状态变为阻塞状态。可见,进程的阻塞是进程自身的一种主动行为,也因此只有处于运行态的进程(获得CPU),才可能将其转为阻塞状态。当进程进入阻塞状态,是不占用CPU资源的

文件描述符fd

文件描述符(File descriptor)是计算机科学中的一个术语,是一个用于表述指向文件的引用的抽象化概念。

文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。

缓冲I/O

缓存 I/O 又被称作标准 I/O,大多数文件系统的默认 I/O 操作都是缓存 I/O。在 Linux 的缓存 I/O 机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓存( page cache )中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。

缓存 I/O 的缺点:
数据在传输过程中需要在应用程序地址空间和内核进行多次数据拷贝操作,这些数据拷贝操作所带来的 CPU 以及内存开销是非常大的。

IO模式

对于一次性IO访问(以read为例子),会将数据先拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间,

当一次read操作发生时

A.等待数据准备

B.将数据从内核拷贝到进程中

正因为有上面2个步骤,linux系统产生了下面5种网络模式方案

---阻塞 I/O           ->收快递,快递如果不到,就干不了其他的活

---非阻塞I/0       ->收快递,不断的去问,有没有送到,有没有送到,...如果送到了就接收

---I/O多路复用      ->找个代理人(select), 去收快递。快递到了,就通知用户.  

---信号驱动I/O  (不常用)

---异步I/O        ->比较复杂,看转载内容吧.

主要来了解下I/O多路复用内容:

1.这就是我们说的select,poll,epoll ,好处就是单个进程(process)就可以同时处理多个网络连接的IO,基本原理就是select这个函数,会不断的轮询所负责的所有socket

2.当某个socket有数据了,就返回给用户。 当用户调用了select,那么整个进程会被阻塞(block).

3.同时,kernel会'监视'所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回,这个时候用户在调用read操作,将数据从kernel拷贝到用户进程

4.所有IO多路复用的特点是通过一种机制一个进程能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中的任意一个进入读的状态,select函数就可以返回 ----   select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作 -

5.select/epoll的优势并不是单个连接能处理得更快,而是在于处理更多的连接

6.在IO multiplexing Model中,实际中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。

-----还有很多详细的知识点,还是见文章顶头吧

blocking和non-blocking的区别

调用blocking IO 会一直block 对应的进程,直到操作完成

调用non-blcoking在kernel还没准备好数据的情况下,会立即返回

synchronous IO和asynchronous IO的区别 (同步IO和异步IO区别)

两者的区别: 同步IO在IO操作(IO operation)的时候会将整个进程阻塞,......(这里居然blcoking和non-blocking都是同步IO------!!!)

因为!:定义中所指的"IO operation"(IO操作)是指真实的IO操作, 当kernel中数据准备好的时候,recvfrom(接收数据) 会将数据从kernel拷贝到用户内存中,这个时候进程是被block了。

然而,异步IO则不一样,当进程发起IO操作之后,就直接返回了再也不用管了,一直等到kernel发送一个信号,告诉进程说IO完成,在这个过程中,进程完全没有被block.

select,poll,epoll都是IO多路复用的机制。I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间

select

是通过一个select()系统调用来监视多个文件描述符的属组,当select()返回后,该数组中就绪的文件描述符便会内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作

select()一个缺点,单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制

select()所维护的存储大量文件描述符的数据结构,随着文件描述符数量的增大,其复制的开销也线性增长。同时,由于网络响应时间的延迟使得大量TCP连接处于非活跃状态,但调用select()会对所有socket进行一次线性扫描,所以这也浪费了一定的开销

 select(rlist, wlist, xlist, timeout=None)
 readable, writeable, exeptional = select.select(inputs,outputs,inputs)   #加入select监控

select函数监视的文件描述符分为3类,

1.read_fds  监视的可读文件句柄集合

2.write_fds 监视的可写文件句柄集合

3.excepr_fds 监视的异常文件句柄集合

4. timeout 本次select()的超时结束时间。

但是! 调用select()函数会阻塞,直到有描述符就绪(有数据 可读,可写,或者except,或者timeout),当select函数返回后, 可以遍历fdset(文件描述符集合),来找到就绪的描述符--

    这里我有点模糊。但是没关系,后面有个ftp的server端用到这块,就明白了--

poll----不会!!

select和poll都需要在返回后,通过遍历文件描述符来获取已经就绪的socket。事实上,同时连接的大量客户端在一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。

而且!python的select()方法是直接调用的操作系统的IO接口,这个接口监控了sockets,openfiles, and pipie(所有带fileno()方法的文件句柄) 何时变成readable(可读的)和writeable(可写的)或者通信错误,,select()使得同时监控多个连接变的简单,并且这比写一个长循环来等待和监控多客户端连接要高效,因为select直接通过操作系统提供的C的网络接口进行操作,而不是通过Python的解释器

在上面第二个代码中,:select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接收所有要发出去的data(outgoing data),第3个监控错误信息。

IO多路复用概念

#补:
关于缓冲IO: 在linux的缓冲IO中,操作系统会将IO数据缓存在文件系统的页缓存中,也就是说,数据会被先拷贝到内核空间,然后在从内核空间拷贝到用户空间
通俗来说,应用程序是不能直接去访问邮件的,一定是调用操作系统的接口,数据会被先copy到内核态,然后再从内核态copy到用户态 
那总不能一个字节的数据过来一次就copy一次,那多没有效率,所以就有了缓存区, 等缓存区满了后,会统一把数据copy到用户态.
 
 
通常,我们写服务器处理模型的程序时,有以下几种模型:
(1)每收到一个请求,创建一个新的进程,来处理该请求;
(2)每收到一个请求,创建一个新的线程,来处理该请求;
(3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求
上面的几种方式,各有千秋,
第(1)中方法,由于创建新的进程的开销比较大,所以,会导致服务器性能比较差,但实现比较简单。
第(2)种方式,由于要涉及到线程的同步,有可能会面临死锁等问题。
第(3)种方式,在写应用程序代码时,逻辑比前面两种都复杂。
综合考虑各方面因素,一般普遍认为第(3)种方式是大多数网络服务器采用的方式
 
回调函数:特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应

三种网络编程范式:

单线程 同步
多线程
事件驱动编程模型  最主流的,底层就是通过事件驱动来实现的, 采取异步之后 效率就会变高了。 nginx就是采用这个异步模式
 
那协程怎么实现检测所有的IO:每个IO来的时候,就会注册一个事件,然后协程自己还有一个线程不断的去事件驱动队列中,拿出这个事件来处理.
 
事件驱动型程序比多线程程序更容易推断出行为,因为程序员不需要关心线程安全问题(多线程中锁的问题)

那在什么情况下使用事件驱动模型?

1.程序中有很多任务,
2.任务之间高度独立(就是它们之间不需要互相通信,或者彼此等待)
3.在等待事件到来时,某些任务会阻塞
4.当应用程序需要在任务间共享可变的数据时,这也是个选择,因为这里不需要采用同步处理.
 
事件驱动模型中,只要一遇到IO操作就注册一个事件,然后主程序就可以继续干其它的事情了,只要IO处理完毕后,继续恢复之前中断的任务
就用到了select模块!!
 而且!注意 写IO多复用程序,如何一个地方都不能有阻塞,只要有阻塞,整个程序就会卡,因为它是单线程啊!!

IO多路复用概念性的更多相关文章

  1. Python(七)Socket编程、IO多路复用、SocketServer

    本章内容: Socket IO多路复用(select) SocketServer 模块(ThreadingTCPServer源码剖析) Socket socket通常也称作"套接字" ...

  2. IO多路复用之select总结

    1.基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程.IO多路复用适用如下场合: (1)当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/ ...

  3. IO多路复用之poll总结

    1.基本知识 poll的机制与select类似,与select在本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是poll没有最大文件描述符数量的限制.poll和selec ...

  4. IO多路复用之epoll总结

    1.基本知识 epoll是在2.6内核中提出的,是之前的select和poll的增强版本.相对于select和poll来说,epoll更加灵活,没有描述符限制.epoll使用一个文件描述符管理多个描述 ...

  5. python中的IO多路复用

    在python的网络编程里,socetserver是个重要的内置模块,其在内部其实就是利用了I/O多路复用.多线程和多进程技术,实现了并发通信.与多进程和多线程相比,I/O多路复用的系统开销小,系统不 ...

  6. socket的IO多路复用

    IO 多路复用 I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. Linux Linux中的 select,poll, ...

  7. IO多路复用及ThreadingTCPServer源码阅读

    IO多路复用 socket模块是阻塞的,通过socket建立的服务端可以接收多个请求,但只能同时处理一个请求,其他请求都被阻塞.可以通过IO多路复用解决这个问题,socketserver内部使用的就是 ...

  8. 【知乎网】Linux IO 多路复用 是什么意思?

    提问一: Linux IO多路复用有 epoll, poll, select,知道epoll性能比其他几者要好.也在网上查了一下这几者的区别,表示没有弄明白. IO多路复用是什么意思,在实际的应用中是 ...

  9. Python自动化之IO多路复用

    单线程.多线程和异步对比图 灰色的是阻塞 IO多路复用 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心 ...

随机推荐

  1. 在DevExpress程序中使用Winform分页控件直接录入数据并保存

    一般情况下,我们都倾向于使用一个组织比较好的独立界面来录入或者展示相关的数据,这样处理比较规范,也方便显示比较复杂的数据.不过在一些情况下,我们也可能需要直接在GridView表格上直接录入或者修改数 ...

  2. Redis命令拾遗三(列表List类型)

    本文版权归博客园和作者吴双本人共同所有.转载和爬虫请注明原文地址 Redis五种数据类型之列表类型 Redis五种数据类型之列表类型.你可以存储一个有序的字符串列表一类数据.比如你想展示你所存储的所有 ...

  3. GridView中显示时间日期格式问题

    以下都是GridView基本常用的日期,时间格式 形式 语法 结果 注释 数字 {0:N2} 12.36   数字 {0:N0} 13   货币 {0:c2} $12.36   货币 {0:c4} $ ...

  4. Xamarin Android 之起始篇

    序言: 在博客园注册了已经有2年多了,快三年了.从开始学习这一行开始就在博客园注册了这个账号.至今也还没有写过一篇随笔,大多时候都是在园子里头潜水,看大牛写的文章,学习. 写博客不为啥,就是自己对自己 ...

  5. C++_系列自学课程_第_12_课_结构体

    #include <iostream> #include <string> using namespace std; struct CDAccount { double bal ...

  6. Java 内存区域与内存溢出

    内存区域 Java 虚拟机在执行 Java 程序的过程中会把他所管理的内存划分为若干个不同的数据区域.Java 虚拟机规范将 JVM 所管理的内存分为以下几个运行时数据区:程序计数器.Java 虚拟机 ...

  7. 时间戳TimeStamp处理

     我获得这个时间戳是得想除以1000再处理的,看看你们的需要先除多少再处理 //时间戳处理 NSInteger time = timeStamp / 1000; NSNumber *timer = [ ...

  8. SQL server学习

    慕课网sql server学习 数据库第一印象:desktop--web server--database server** 几大数据库:sql server.oracle database.DB2. ...

  9. 读取properties配置文件的方法

    一般在.properties文件中配置数据库连接的相关信息,我们需要从中读取信息,以便建立与数据库的连接. 文件目录: application.properties配置信息: url=jdbc:ora ...

  10. Hadoop技巧系列索引

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink Hadoop技巧(01):插件,终端权限 Had ...