array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 第3章 文件I/O(5)_五种I/O模型 - 爱码网

6. I/O处理方式(5种I/O模型)

6.1 几个概念的辨析

(1)同步和异步

  ①是访问数据的方式,主要是针对IO(资源、数据)而言的。关键在于I/O操作完成后,有没有提供通知机制。

  ②同步的IO,要求进(线)程主动去读写数据,在读写过程还是会阻塞。而异步I/O操作时,进程不主动读写数据,而是内核完成数据读写完成以后将通知进(线)程。

(2)阻塞和非阻塞

  ①是针对进(线)程而言的,进程要访问的数据是否就绪,是否需要等待。

  ②阻塞与非阻塞是针对同步应用而言的。IO操作分为两个阶段:等待数据和数据从内核到用户态的拷贝。对于阻塞,这两个阶段进(线)程都会被阻塞,而非阻塞的IO操作,在第1阶段可能采用轮询方式而不阻塞,但第2阶段的数据拷贝仍然是阻塞的。

(3)生活中的例子:老张烧开水

  ①老张把水壶普通水壶放到火上,并等待水开(同步阻塞

  ②老张把水壶普通水壶放在火上,去客厅看电视,时不时到厨房看看水开没有。(同步非阻塞

  ③老张把响水壶放到火上,等待水开(异步阻塞,换了一个具有通知功能的响水壶,但老张还是比较傻,只干一件事,就是等待,所以这种模式一般意义不大。)

  ④老张把响水壶放在火上,去客厅看电视,水壶响之前不再去看它,响了再去提壶(异步非阻塞

【小结】

  ①所谓同步、异步是对于水壶而言的普通水壶,同步;响水壶,异步。同步只能让调用者去轮询,看看水壶开了没有。而异步的响水壶在水开后会提醒老张去提壶。

  ②所谓的阻塞、非阻塞,仅仅对于老张而言等待的老张,阻塞,这时可能媳妇喊他都不知道看电视的老张,而非阻塞的。

6.2 五种I/O模型

(1)阻塞I/O模型若所调用的I/O函数没有完成相关的功能就会使进程挂起,直到相关数据到达才会返回。如:终端、网络设备的访问。整个过程分为两个阶段:

  ①阶段一是等待数据就绪网络I/O的情况就是等待远端数据陆续抵达;磁盘I/O的情况就是等待磁盘数据从磁盘上读取到内核态内存中。

  ②阶段二是数据拷贝出于系统安全,用户态的程序没有权限直接读取内核态内存,因此内核负责把内核态内存中的数据拷贝一份到用户态内存中。理解这两个阶段非常重要,后续I/O模型的演变都是针对这两个阶段进行不同改造。

第3章 文件I/O(5)_五种I/O模型 

(2)非阻塞模型:当请求的I/O操作不能完成时,则不让进程休眠,而且返回一个错误。如open、read和write访问。

第3章 文件I/O(5)_五种I/O模型 

  ①阶段一频繁轮询的话,也很耗费CPU时间这种方式对单个I/O请求意义不大,但给I/O多路复用铺平了道路。 低速系统调用时,进程可能会阻塞。

  ②非阻塞I/O操作(open、read、write)不阻塞,如果操作不能完成,则出错返回

  ③设定非阻塞的方式:使用open打开文件,设置O_NONBLOCK标志。如果一个文件己经打开,则使用fcntl修改文件状态标志。

(3)I/O多路转接模型:如果请求的I/O操作阻塞,且他不是真正阻塞I/O,而且让其中的一个函数等待,在这期间,I/O还能进行其他操作。如:select函数。

  ①调用 select/poll该方法由一个用户态线程负责轮询多个sockets,直到某个阶段一的数据就绪,再通知实际的用户线程执行阶段二的拷贝

  ②通过一个专职的用户态线程执行非阻塞I/O轮询,模拟实现了阶段一的异步化。

 第3章 文件I/O(5)_五种I/O模型 

(4)信号驱动I/O模型:在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动I/O。(类似于观察者模式)阶段一演变为异步,由内核托管,应用程序只需告知内核,当阶段一数据就绪时向应用程序发出 SIGIO信号。至此为止,前述4种模型的阶段二仍是处于block状态的

第3章 文件I/O(5)_五种I/O模型 

(5)异步I/O模型:在这种模型下,当一个描述符己准备好,可以启动I/O时,进程会通知内核。由内核进行后续处理。当整个过程(包括阶段一和阶段二)全部完成时,通知应用程序来读数据。这种用法现在较少。

第3章 文件I/O(5)_五种I/O模型 

6.3 五种模型的比较

第3章 文件I/O(5)_五种I/O模型 

【编程实验】非阻塞I/O的read调用。

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include "io.h"

int main(void)
{
    char buffer[4096] = {0};
    ssize_t size = 0;

    //默认,IO是阻塞的,后面的read会阻塞等待键盘输入。
    //以下演示非阻塞IO的读取。
    set_fl(STDIN_FILENO, O_NONBLOCK);

    sleep(5);
    
    size = read(STDIN_FILENO, buffer, sizeof(buffer));

    if(size < 0 ){
        perror("read error");
        exit(1);
    }else if (size == 0){
        printf("read finished\n");//进程执行过程中,在没有键盘输入并按ctrl+D
                                  //会执行到这里。
    }else{
        if(write(STDOUT_FILENO, buffer, size) != size){
            perror("write error");
            exit(1);
        }
    }
    

    return 0;
}

相关文章: