同步与异步
        同步就是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成。
        异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了,异步一般使用状态、通知和回调。
 
阻塞与非阻塞
        阻塞是指调用结果返回之前,当前线程会被挂起,一直处于等待消息通知,不能够执行其他业务。
       非阻塞是指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
 
五种IO模型
        对于一次IO访问,数据会先被拷贝到内核的缓冲区中,然后才会从内核的缓冲区拷贝到应用程序的地址空间。需要经历两个阶段:
            1. 准备数据
            2. 将数据从内核缓冲区拷贝到进程地址空间 
        由于存在这两个阶段,Linux产生了下面五种IO模型。
阻塞IO
        当用户进程调用了recvfrom调用时,内核进入IO的第一个阶段:准备数据(内核需要等待足够的数据再拷贝),这个过程需要等待,用户进程会被阻塞,等内核将数据准备好,然后拷贝到用户地址空间,内核返回结果,用户进程才从阻塞态进入就绪态。
        Linux中,默认情况下所有的socket都是阻塞的。
 
非阻塞IO
        当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存,然后返回。
        非阻塞IO模式下用户进程需要不断地询问内核的数据准备好了没有。
        Linux下,可以通过设置socket使其变为non-blocking。
 
IO多路复用
        通过一种机制,一个进程可以监视多个文件描述符(套接字描述符),一旦某个文件描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。这样就不需要每个用户进程不断的询问内核数据准备好了没有。
        常用的IO多路复用方式有select、poll和epoll。
        
    select
        kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
 
        select 函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述副就绪(有数据可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以通过遍历fdset,来找到就绪的描述符。
        select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024。
 
    poll
        poll使用一个 pollfd的指针实现。
int poll (struct pollfd *fds, unsigned int nfds, int timeout);
 
  pollfd结构包含了要监视的event和发生的event
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events to watch */
short revents; /* returned events witnessed */
};
 
        和select函数一样,poll返回后,需要遍历pollfd来获取就绪的描述符。poll没有监听最大数量限制。
    
    epoll
        epoll使用一个文件描述符管理多个描述符,将用户关心的文件描述符的事件存放到内核的一个事件表中,采用监听回调的机制,这样在用户空间和内核空间的copy只需一次,避免再次遍历就绪的文件描述符列表。
        epoll的操作过程需要三个接口:
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
 
        int epoll_create(int size);
        创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。
        int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
        对指定描述符fd执行op操作。
        - epfd:是epoll_create()的返回值。
        - op:表示op操作,用三个宏来表示:添加EPOLL_CTL_ADD,删除EPOLL_CTL_DEL,修改EPOLL_CTL_MOD。分别添加、删除和修改对fd的监听事件。
        - fd:是需要监听的fd(文件描述符)
        - epoll_event:是告诉内核需要监听什么事,struct epoll_event结构如下:
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
}; //events可以是以下几个宏的集合:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
 
        int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
        等待epfd上的io事件,最多返回maxevents个事件。
        参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回0表示已超时。
 
    epoll的两种工作模式
        LT(level trigger,水平触发)模式:当epoll_wait检测到描述符就绪,将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。LT模式是默认的工作模式。
        LT模式同时支持阻塞和非阻塞socket。
 
  ET(edge trigger,边缘触发)模式:当epoll_wait检测到描述符就绪,将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。
       ET是高速工作方式,只支持非阻塞socket。ET模式减少了epoll事件被重复触发的次数,因此效率要比LT模式高。
 
异步IO
        用户进程发起read操作之后,立刻就可以开始去做其它的事。内核收到一个异步IO read之后,会立刻返回,不会阻塞用户进程。内核会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,内核会给用户进程发送一个signal,告诉它read操作完成了。
    
信号驱动IO
        内核文件描述符就绪后,通过信号通知用户进程,用户进程再通过系统调用读取数据。此方式属于同步IO,因为实际读取数据到用户进程缓存的工作仍然是由用户进程自己负责的。
参考:https://segmentfault.com/a/1190000003063859
 
 
 
 

linux网络编程IO模型的更多相关文章

  1. Linux网络编程-IO复用技术

    IO复用是Linux中的IO模型之一,IO复用就是进程预先告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程进程处理,从而不会在单个IO上阻塞了.Linux中,提 ...

  2. LINUX网络编程 IO 复用

    参考<linux高性能服务器编程> LINUX下处理多个连接时候,仅仅使用多线程和原始socket函数,效率十分低下 于是就出现了selelct poll  epoll等IO复用函数. 这 ...

  3. linux网络编程 IO多路复用 select epoll

    本文以我的小型聊天室为例,对于服务器端的代码,做了三次改进,我将分别介绍阻塞式IO,select,epoll . 一:阻塞式IO 对于聊天室这种程序,我们最容易想到的是在服务器端accept之后,然后 ...

  4. Linux 网络编程(IO模型)

    针对linux 操作系统的5类IO模型,阻塞式.非阻塞式.多路复用.信号驱动和异步IO进行整理,参考<linux网络编程>及相关网络资料. 阻塞模式 在socket编程(如下图)中调用如下 ...

  5. Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)

    Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...

  6. Linux 网络编程的5种IO模型:信号驱动IO模型

    Linux 网络编程的5种IO模型:信号驱动IO模型 背景 上一讲 Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 我们讲解了多路复用等方面的知识,以及有关例程. ...

  7. Linux 网络编程的5种IO模型:异步IO模型

    Linux 网络编程的5种IO模型:异步IO模型 资料已经整理好,但是还有未竟之业:复习多路复用epoll 阅读例程, 异步IO 函数实现 背景 上一讲< Linux 网络编程的5种IO模型:信 ...

  8. linux网络编程模型

    1.编程模型 Linux网络编程模型是基于socket的编程模型

  9. Linux网络编程(四)

    在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...

随机推荐

  1. 第十一周(11.24-12.01)----WBS功能分解

    功能 子功能 二级子功能 预计花费时间(小时) 游戏基础功能 显示首界面 绘制产产品主logo及不同难度下的布局 4   游戏 难度选择(初级.中级.高级) 4     退出整个程序 1     放弃 ...

  2. docker cp 和docker exec 查看docker 运行的容器信息

    1. 使用docker 运行 redis 和 postgresql docker run -d -p : -v /redis/data/:/data redis docker run -d -p : ...

  3. golang yaml配置文件解析

    yaml文件语法 此模块内容转自:http://www.ruanyifeng.com/blog/2016/07/yaml.html 大小写敏感 使用缩进表示层级关系 缩进时不允许使用Tab键,只允许使 ...

  4. no-referrer-when-downgrade什么意思

    no referrer when downgrade的意思:降级时不推荐. 从一个网站链接到另外一个网站会产生新的http请求,referrer是http请求中表示来源的字段. no-referrer ...

  5. 4 vuex的安装

    安装可以看,引入又问题https://blog.csdn.net/u014196765/article/details/78022065?locationNum=9&fps=1(引入) htt ...

  6. 如何设置Listbox的行间距?

    关于Listbox的问题? 1. 如何设置Listbox的行间距?  2. 如何实现当鼠标点击Listbox时,被选中的那一行在鼠标点击处出现一控件?    也就是怎么计算出被选中的那一行鼠标点击处的 ...

  7. 提升jmeter自身性能

    JMeter负载测试时使用GUI界面和较多的收集测试结果的监听器容易造成jmeter的性能瓶颈,远程测试时的控制台尤为明显.提升JMeter负载测试时性能的方法如下: 官方的解决办法:http://j ...

  8. Influxdb安装部署

    1.下载Influxdb并解压 2.下载上图中的nssm(辅助性工具) 3.  在安装目录执行cmd 输入 nssm install influxdb,其中Path选择安装文件中的influxd,Ar ...

  9. REQUIRES_NEW 如果不在一个事务那么自己创建一个事务 如果在一个事务中 自己在这个大事务里面在创建一个子事务 相当于嵌套事务 双层循环那种

    REQUIRES_NEW   如果不在一个事务那么自己创建一个事务 如果在一个事务中 自己在这个大事务里面在创建一个子事务  相当于嵌套事务 双层循环那种 不管是否存在事务,业务方法总会自己开启一个事 ...

  10. SSM 项目搭建 (IDEA)

    好好想了想,还是准备给大家发一个简单的SSM的项目搭建教程. 我觉得通常来说,只是XML的配置文件可能让人头痛了点,其他的倒真不是问题. 不过话说回来,mybatis一直让我觉得用起来不方便.因为数据 ...