内核空间和用户空间:
由于操作系统都包括内核空间和用户空间(或者说内核态和用户态),内核空间主要存放的是内核代码和数据,是供系统进程使用的空间。而用户空间主要存放的是用户代码和数据,是供用户进程使用的空间。目前Linux系统简化了分段机制,使得虚拟地址与线性地址总是保持一致,因此,Linux系统的虚拟地址也是0-4G。Linux系统将这4G空间分为了两个部分:将最高的1G空间(从虚拟地址0xC0000000到0xFFFFFFFF)供内核使用,即为“内核空间”,而将较低的3G空间(从虚拟地址 0x00000000到0xBFFFFFFF)供用户进程使用,即为“用户空间”。同时由于每个用户进程都可以通过系统调用进入到内核空间,因此Linux的内核空间可以认为是被所有用户进程所共享的,因此对于一个具体用户进程来说,它可以访问的虚拟内存地址就是0-4G。另外Linux系统分为了四种特权级:0~3,主要是用来保护资源。0级特权最高,而3级则为最低,系统进程主要运行在0级,用户进程主要运行在3级。
一般来说,IO操作都分为两个阶段,就拿套接口的输入操作来说,它的两个阶段主要是:
1)等待网络数据到来,当分组到来时,将其拷贝到内核空间的临时缓冲区中
2)将内核空间临时缓冲区中的数据拷贝到用户空间缓冲区中

服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:

(1)同步阻塞IO(Blocking IO):即传统的IO模型。

(2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。注意这里所说的NIO并非Java的NIO(New IO)库。

(3)IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型。

(4)异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO。

同步和异步的概念描述的是用户线程与内核的交互方式:同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;而异步是指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。

阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式:阻塞是指IO操作需要彻底完成后才返回到用户空间;而非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。

对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的process (or thread),另一个就是系统内核(kernel)。当一个read操作发生时,它会经历两个阶段:
 1 等待数据准备 (Waiting for the data to be ready)
 2 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)
记住这两点很重要,因为这些IO Model的区别就是在两个阶段上各有不同的情况。

阻塞式I/O模型
产生阻塞的原因
linux进程调度算法-时间片调度算法
每个进程占用CPU一个时间片后被挂起
当前运行进程如果需要等待其他系统资源,且不是非阻塞方式运行,将进入等待状态

设置socket为非阻塞方式
函数fcntl
int flags;
flag=fcntl(sockfd,F_GETFL,0);
fcntl(sockfd,F_SETFL,flag|O_NONBLOCK);
函数ioctl
int on=1;
ioctl(sockfd,FIONBIO,&on);

非阻塞式I/O模型对4种I/O操作返回的错误
读操作
接收缓冲区无数据时返回EWOULDBLOCK
写操作
发送缓冲区无空间时返回EWOULDBLOCK
空间不够时部分拷贝,返回实际拷贝字节数
建立连接
启动3次握手,立刻返回错误EINPROGRESS
服务器客户端在同一主机上connect立即返回成功
接受连接
没有新连接返回EWOULDBLOCK

阻塞式I/O模型的超时控制
调用alarm函数设置超时
超时到达时产生SIGALARM信号中断I/O函数阻塞,对于4种产生阻塞的函数均有效
多次调用alarm时,产生的SIGALARM信号无法区分是哪一次超时引发的,无法实现超时控制
示例:alarmio.cpp

当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
这个图和blocking IO的图其实并没有太大的不同,事实上,还更差一些。因为这里需要使用两个system call (select 和 recvfrom),而blocking IO只调用了一个system call (recvfrom)。但是,用select的优势在于它可以同时处理多个connection。(多说一句。所以,如果处理的连接数不是很高的话,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大。select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。)
在IO multiplexing Model中,实际中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。

注意1:select函数返回结果中如果有文件可读了,那么进程就可以通过调用accept()或recv()来让kernel将位于内核中准备到的数据copy到用户区。

注意2: select的优势在于可以处理多个连接,不适用于单个连接

阻塞式I/O模型的超时控制
设置socket选项
设置SO_RCVTIMEO和SO_SNDTIMEO选项
设置了这两个选项之后,所有的读写操作可以保证在超时范围内返回
只需设置一次选项,对以后的读写操作均有效
不适用于accept和connect
示例:timeoutio.cpp

I/O模型详细解析的更多相关文章

  1. flex盒模型 详细解析

    flex盒模型 详细解析 移动端页面布局,采用盒模型布局,效果很好 /* ============================================================    ...

  2. 5.java内存模型详细解析

    一. java结构体系 Description of Java Conceptual Diagram(java结构) 我们经常说到JVM调优,JVM和JDK到底什么关系,大家知道么?这是java基础. ...

  3. 【转】JDK5.0中JVM堆模型、GC垃圾收集详细解析

    基本概念 堆/Heap JVM管理的内存叫堆:在32Bit操作系统上有4G的限制,一般来说Windows下为2G,而Linux下为3G:64Bit的就没有这个限制.JVM初始分配的内存由-Xms指定, ...

  4. C++多态的实现及原理详细解析

    C++多态的实现及原理详细解析 作者: 字体:[增加 减小] 类型:转载   C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型 ...

  5. 目标检测从入门到精通—R-CNN详细解析(二)

    R-CNN目标检测详细解析 <Rich feature hierarchies for Accurate Object Detection and Segmentation> Author ...

  6. java中JVM虚拟机内存模型详细说明

    java中JVM虚拟机内存模型详细说明 2012-12-12 18:36:03|  分类: JAVA |  标签:java  jvm  堆内存  虚拟机  |举报|字号 订阅     JVM的内部结构 ...

  7. java类生命周期详细解析

    (一)详解java类的生命周期 引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前 ...

  8. springmvc 项目完整示例06 日志–log4j 参数详细解析 log4j如何配置

    Log4j由三个重要的组件构成: 日志信息的优先级 日志信息的输出目的地 日志信息的输出格式 日志信息的优先级从高到低有ERROR.WARN. INFO.DEBUG,分别用来指定这条日志信息的重要程度 ...

  9. include_path详细解析

    include_path详细解析     原文地址:http://www.laruence.com/2010/05/04/1450.html 1.php默认的包含路径为 .;C:\php\pear 即 ...

随机推荐

  1. Xcode 7 你能不能再抗扎腾点儿呢 - 尤其自个儿强制升级后,没事儿就关闭

    Xcode 7 你能不能再抗扎腾点儿呢 - 尤其自个儿强制升级后,没事儿就关闭 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用 ...

  2. 【Sqlserver系列】初级思维导图

    1   概述 本篇文章主要概述Sqlserver思维导图. 2   具体内容 3   参考文献 [01]https://mp.weixin.qq.com/s/USNMslpvu7pWosMZnVTPd ...

  3. Docker 搭建 etcd 集群

    阅读目录: 主机安装 集群搭建 API 操作 API 说明和 etcdctl 命令说明 etcd 是 CoreOS 团队发起的一个开源项目(Go 语言,其实很多这类项目都是 Go 语言实现的,只能说很 ...

  4. iOS OC Swift3.0 TableView 中tableviewcell的线左边不到边界

    Swift 3.0 func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt index ...

  5. ABP 用swagger UI测试API报401无权限访问问题

    问题描述: 当我们用swagger UI对Web API 进行测试时报401错误 我们点开GET /api/services/app/Role/GetAll,输入参数 点击Try it out!按钮, ...

  6. Servlet小总结

    Servlet Servlet(服务器端小程序)是使用Java语言编写的服务器端程序,像JSP一样,生成动态的Web页.Servlet主要运行在服务器端,并由服务器调用执行. Servlet处理的基本 ...

  7. 王者齐聚!Unite 2017 Shanghai 日程讲师全揭晓

    汇聚了来自全球的 Unity开发者.发行商.培训家及爱好者的 Unite 2017 Shanghai 即将于于 5 月 11 日-13日在上海·国际会议中心隆重举行.Unite 大会是由 Unity ...

  8. C# TreeView 控件的综合使用方法

    1.概述 该篇文章开发使用的语言c#,环境visualstudio2010,sql数据库.主要内容包括: (1)treeView控件添加根节点.子节点的基本方法,节点的删除. (2)把treeView ...

  9. C:数据结构与算法之单链表

    单链表相对于顺序表比较难理解,但是比较实用,单链表的插入,删除不需要移动数据元素,只需要一个指针来寻找所需要的元素,还有一个大优点就是不浪费空间,当你想要增加一个结点可以申请(malloc())一个结 ...

  10. 大赛获奖选手专访 | 冷燕冰:最佳设计奖TIMING里的时机和时序

    Mockplus三周年原型设计大赛,从筹备到11月21日完美落幕,50余天的时光,已成为过去.这场近千人参赛的原型设计大赛,我想,无论是于主办方,于参赛选手,于专家评委,还是于每一个关注和参与的人,都 ...