内核空间和用户空间:
由于操作系统都包括内核空间和用户空间(或者说内核态和用户态),内核空间主要存放的是内核代码和数据,是供系统进程使用的空间。而用户空间主要存放的是用户代码和数据,是供用户进程使用的空间。目前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. 基于lucene.net 和ICTCLAS2014的站内搜索的实现1

    Lucene.net是一个搜索引擎的框架,它自身并不能实现搜索.须要我们自己在当中实现索引的建立,索引的查找.全部这些都是依据它自身提供的API来实现.Lucene.net本身是基于java的,可是经 ...

  2. tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——NAND 8位硬件ECC

    这节我们实现nand的ecc,保存环境变量到nand flash 中.然后把我们之前的led灯烧写到nand flash 中.开机启动.在 tiny210.h 中定义宏 CONFIG_S5PV210_ ...

  3. JAVA-UML

    UML(UnifiedModelingLanguage)(统一建模语言或标准建模语言) 它是模型化的软件系统开发图形语言 为软件开发所有阶段提供模型化,可视化支持 UM2.2中定义了14中图示 三种常 ...

  4. 一位10年Java工作经验的架构师聊Java和工作经验

    从事近十年的 JavaEE 应用开发工作,现任阿里巴巴公司系统架构师.对分布式服务架构与大数据技术有深入研究,具有丰富的 B/S 架构开发经验与项目实战经验,擅长敏捷开发模式.国内开源软件推动者之一, ...

  5. Node.js显示页面

    首先我们先要下载并安装Nodejs,然后进入Node.js中安装supervisor, npm -g install supervisor -g表示全局模式 (无论windows哪一个用户登陆都可以使 ...

  6. Mybatis中的模糊查询

    今天下午做的一个功能,要用到模糊查询,字段是description,刚开始我的写法用的是sql中的模糊查询语句, 但是这个有问题,只有将字段的全部值传入其中,才能查询,所以不是迷糊查询. 后来经过搜索 ...

  7. 【1】ArcGIS API for JavaScript 4.5/4.6 本地部署

    惭愧,和我的学弟比起来,我所开始接触前端开发,ArcGIS API for JavaScript的时间和深度远远不及于他. 一年之尾,亦是一年之始,我也将正式开始我的博客生涯.本人在校学习并且做项目, ...

  8. [置顶] android ListView包含Checkbox滑动时状态改变

    题外话: 在xamarin android的开发中基本上所有人都会遇到这个小小的坎,的确有点麻烦,当时我也折腾了好一半天,如果你能看到这篇博客,说明你和我当初也是一样的焦灼,如果你想解决掉这个小小的坎 ...

  9. js 深入理解原型模式

    我们创建每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象.使用原型的好处是可以让所有对象共享它所包含的属性和方法. function Person(){ } Pers ...

  10. ES6 函数的扩展3

    箭头函数 基本用法 ES6允许使用"箭头"(=>)定义函数 var f = v => v; 上面的箭头函数等同于: var f = function(v) { retu ...