在了解IO模型前,先了解什么叫IO,IO得操作是怎么样的?

IO既输入输出,指的是一切操作程序或设备与计算机之间发生的数据传输的过程。它分为IO设备和IO接口两个部分。

  • IO设备:就是指可以与计算机进行数据传输的硬件。最常见的I/O设备有打印机、硬盘、键盘和鼠标。从严格意义上来讲,它们中有一些只能算是输入设备(比如说键盘和鼠标);有一些只是输出设备(如打印机)。
  • IO接口:就是是主机和外设之间的交接界面,通过接口可以实现主机和外设之间的信息交换。

那IO是怎么操作这些进行数据的传输呢?

而用户进程中的一个完整IO分为两个阶段:

  • 用户空间与内核空间交互
  • 内核空间与设备空间交互

Linux中的五种IO模型有阻塞IO模型、非阻塞IO模型、信号驱动IO模型、IO多路复用模型、异步IO模型。通常有同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式。

同步与异步

  • 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事。(死等结果)
  • 所谓异步,就是当一个异步过程调用发出后,调用者不能立刻得到结果,调用者不用等待这件事完成,可以继续做其他的事情。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。(回调通知)

阻塞与非阻塞

  • 阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,CPU不会给线程分配时间片,即线程暂停运行)。函数只有在得到结果之后才会返回。
  • 非阻塞调用是指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

总的来说就是:同步与异步是 两个对象之间的关系,而阻塞与非阻塞是一个对象的状态

阻塞IO模型(blocking I/O)

场景描述

点完餐后,不知道什么时候能做好,只好坐在餐厅里面等,直到做好,然后吃完才离开。但是不知道饭能什么时候做好,只好在餐厅等,而不能去逛街,直到吃完饭才能去逛街,中间等待做饭的时间浪费掉了。这就是典型的阻塞。

优点:

  1. 能够及时返回数据,无延迟;
  2. 对内核开发者来说这是省事了; 缺点:
  3. 对用户来说处于等待就要付出性能的代价了;

非阻塞IO模型(nonblocking I/O)

场景描述

我女友不甘心白白在这等,又想去逛商场,又担心饭好了。所以我们逛一会,回来询问服务员饭好了没有,来来回回好多次,饭都还没吃都快累死了啦。这就是非阻塞。需要不断的询问,是否准备好了。

同步非阻塞就是 “每隔一会儿瞄一眼进度条” 的轮询(polling)方式。所以,非阻塞 IO的特点是用户进程需要不断的主动询问kernel数据好了没有。

优点:能够在等待任务完成的时间里干其他活了(包括提交其他任务,也就是 “后台” 可以有多个任务在同时执行)。

缺点:任务完成的响应延迟增大了,因为每过一段时间才去轮询一次read操作,而任务可能在两次轮询之间的任意时间完成。这会导致整体数据吞吐量的降低。

IO多路复用模型(I/O multiplexing)

场景描述

与第二个方案差不多,餐厅安装了电子屏幕用来显示点餐的状态,这样我和女友逛街一会,回来就不用去询问服务员了,直接看电子屏幕就可以了。这样每个人的餐是否好了,都直接看电子屏幕就可以了,这就是典型的IO多路复用

I/O多路复用的主要应用场景如下:

  1. 服务器需要同时处理多个处于监听状态或者多个连接状态的套接字。
  2. 服务器需要同时处理多种网络协议的套接字。

在IO 多路复用模型中,对于每一个socket,一般都设置成为non-blocking,但是,整个用户的进程其实是一直被block的。只不过进程是被select这个函数block,而不是被socket IO给block。所以IO多路复用是阻塞在select,epoll这样的系统调用之上,而没有阻塞在真正的I/O系统调用上。

然后下面来几个IO操作例子:

阻塞:

int main()
{int sockfd = socket(AF_INET,SOCK_STREAM,0);struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(9999);addr.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");bind(sockfd,(struct sockaddr *)&addr,sizeof(addr));listen(sockfd,10);int fd[5];for(int i = 0;i < 5;i++){fd[i] = accept(sockfd,NULL,NULL);}printf("accept 5 ok\n");//在进程中与5个客户端进行通信char buf[20];bzero(buf,20);read(fd[0],buf,20);//阻塞等待fd[0]进行读操作,才能继续执行printf("buf is %s\n",buf);bzero(buf,20);read(fd[1],buf,20);printf("buf is %s\n",buf);bzero(buf,20);read(fd[2],buf,20);printf("buf is %s\n",buf);bzero(buf,20);read(fd[3],buf,20);printf("buf is %s\n",buf);bzero(buf,20);read(fd[4],buf,20);printf("buf is %s\n",buf);
}

通过例子可以发现,如果fd[0]没有打印,那么后面将都不会打印。既阻塞等待fd[0]的IO操作之后在进行其他fd里面的操作。

非阻塞:

int main()
{int sockfd = socket(AF_INET,SOCK_STREAM,0);struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(9999);addr.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");bind(sockfd,(struct sockaddr *)&addr,sizeof(addr));listen(sockfd,10);int fd[5];for(int i = 0;i < 5;i++){fd[i] = accept(sockfd,NULL,NULL);//阻塞非阻塞属性是在文件描述符中设置int flag = fcntl(fd[i],F_GETFL);flag = flag | O_NONBLOCK;//添加非阻塞fcntl(fd[i],F_SETFL,flag);//把修改后的属性设置回fd[i]}sleep(10);while(1){int num = 0;//在进程中与5个客户端进行通信char buf[20];bzero(buf,20);num = read(fd[0],buf,20);//非阻塞 bzero(buf,20);read(fd[1],buf,20);printf("buf is %s\n",buf);bzero(buf,20);read(fd[2],buf,20);printf("buf is %s\n",buf);bzero(buf,20);read(fd[3],buf,20);printf("buf is %s\n",buf);bzero(buf,20);read(fd[4],buf,20);printf("buf is %s\n",buf);}
}

非阻塞的缺点就是太占用系统资源了,需要反复的去查看是否接收到信息。

多路复用IO:

int main()
{int sockfd = socket(AF_INET,SOCK_STREAM,0);struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(9999);addr.sin_addr.s_addr = inet_addr("192.168.3.172");bind(sockfd,(struct sockaddr *)&addr,sizeof(addr));listen(sockfd,10);int fd[5];for(int i = 0;i < 5;i++){fd[i] = accept(sockfd,NULL,NULL);}//IO多路复用,应该同时管理多个fdfd_set readfds;//读表FD_ZERO(&readfds);FD_SET(fd[0],&readfds);//把文件描述符加入进表中FD_SET(fd[1],&readfds);FD_SET(fd[3],&readfds);FD_SET(fd[4],&readfds);while(1){fd_set temp = readfds;int num = 0;num = select(fd[4]+1,&temp,NULL,NULL,NULL);//只管理文件描述符的读操作,只监视文件描述符可读if(num > 0){printf("%d\n",num);//把readfds中只剩下可操作的(别的客户端发送了数据,当前fd可读)的文件描述符for(int i = 0; i < fd[4]+1;i++){if ( FD_ISSET(i,&temp) ){   char buf[20];read(i,buf,20);//别人发送了数据,当前i文件描述符,可读printf("fd is %d,data is %s\n",i,buf);}}}}return 0;
}

多路复用IO既谁开始发信号那么就对那个文件描述符进行操作。

IO模型(阻塞,非阻塞,多路复用)相关推荐

  1. IO模型之非阻塞IO

    1. IO模型非阻塞 IO Linux下,可以通过设置socket使其变为 non-blocking.当对一个non-blocking socket执行读操作时,流程是这个样子: 从图中可以看出,当用 ...

  2. 五种IO模型:阻塞/非阻塞/复用/信号驱动/异步IO模型

    五种IO模型:阻塞/非阻塞/复用/信号驱动/异步IO模型 1. IO基本概念 1.1 IO概念 1.2 IO的两个阶段 1.2.1 IO的两个阶段-例子说明 1.2 IO种类 2. 五种IO模型 2. ...

  3. I/O: 阻塞非阻塞I/O 同步异步I/O

    我们知道,在Linux(UNIX)操作系统中,共有五种IO模型,分别是:阻塞IO模型.非阻塞IO模型.IO复用模型.信号驱动IO模型以及异步IO模型. 同步IO模型 阻塞IO模型 我们钓鱼的时候,有一 ...

  4. Java网络编程------IO模型的同步/异步/阻塞/非阻塞(1)

    IO模型的同步/异步/阻塞/非阻塞 一.同步/异步/阻塞/非阻塞 1.同步和异步 2.阻塞和非阻塞 3.同步.异步和阻塞.非阻塞组合 二.IO 1.I/O 2.阻塞IO和非阻塞IO 3.同步IO和同步 ...

  5. 异步就是异步,根本就没有 异步非阻塞IO这个说法。阻塞 非阻塞,同步I/O 异步I/O 的区别

    先给大家安利一下这个 https://www.ibm.com/developerworks/cn/linux/l-async/ 里面关于 异步非阻塞IO 是错的. 异步就是异步,别扯 异步阻塞 异步非 ...

  6. 面试必会系列 - 5.1 网络BIO、NIO、epoll,同步/异步模型、阻塞/非阻塞模型,你能分清吗?

    本文已收录至 Github(MD-Notes),若博客中图片模糊或打不开,可以来我的 Github 仓库,包含了完整图文:https://github.com/HanquanHq/MD-Notes,涵 ...

  7. AIO,BIO,NIO:同步阻塞式IO,同步非阻塞IO,异步非阻塞IO

    BIO,同步阻塞式IO,简单理解:一个连接一个线程 NIO,同步非阻塞IO,简单理解:一个请求一个线程 AIO,异步非阻塞IO,简单理解:一个有效请求一个线程 IO:阻塞IO BIO:同步阻塞IO.服 ...

  8. 两段文章清楚弄明白什么是异步IO、同步IO、同步阻塞IO、同步非阻塞IO、异步阻塞IO、异步非阻塞IO

    百科解释:异步IO_百度百科 先看2,再看1,会理解的更好! 1. 2.阻塞和非阻塞 # 阻塞和非阻塞关注的是程序在等待调用结果时的状态 # 阻塞调用是指调用结果返回之前,当前线程会被挂起.调用线程只 ...

  9. java nio io复用_java 非阻塞IO-java NIO-嗨客网

    Java的NIO教程 NIO 官方名称叫做 New IO,在 JDK 1.4 中相对于 BIO 的新 IO.但是也有很多人称之为 NON-BLOCKING IO.和 BIO 比较的话,叫做非阻塞 IO ...

  10. 同步异步阻塞非阻塞杂记

    版权声明:本文可能为博主原创文章,若标明出处可随便转载. https://blog.csdn.net/Jailman/article/details/78498458 gevent实现的协程是同步非阻 ...

最新文章

  1. 搜索算法,一触即达:GitHub上有个规模最大的开源算法库
  2. 尚硅谷Java视频教程导航(学习路线图)
  3. JSTL1.1函数标签库(functions)如fn:length
  4. 鼠标指针放置上面,显示内容_使鼠标指针远离您键入的内容
  5. 与Min_25筛有关的一些模板
  6. AWS Lambda将数据保存在DynamoDB中
  7. ssm架构 开源项目_6个开源架构项目签出
  8. Docker 集群环境实现的新方式
  9. MongoDBTool - 测试版【GUI美化完毕】 源代码发布 --MongoDB爱好者,Winform爱好者 请进...
  10. RGB转换cv::Mat
  11. Socket通信的安全策略问题
  12. 大专读者被裁,但他却拒绝了42k的Offer?| 一名爬虫工程师自述
  13. Android 开发小TIPS
  14. 在 Linux 平台及 IPv4 环境中构建 IPv6 测试环境
  15. js 解二元一次方程组(消元法)
  16. 学生Web开发人员练习:电影评论II
  17. 手机微信打不开连接到服务器错误代码,微信打不开文件是怎么回事(微信文件错误代码90018)...
  18. 如何更改CSDN博客皮肤
  19. Android本地视频播放器开发--搜索本地视频(1)
  20. 软件测试工程师这个岗位职责是什么?具体都需要干什么?

热门文章

  1. 联合熵、条件熵、互信息、相对熵、交叉熵的详解
  2. 生成自己的数字证书使网站支持HTTPS
  3. JSP+Servlet+Mysql企业财务管理系统设计与实现(附论文)
  4. 通信原理 | FFT/STFT 你真的学会了吗?
  5. 华为AREngine根据深度图获取深度信息
  6. ODBC、JDBC和四种驱动类型
  7. Python---项目3-破解使用crypt方法加密(已加salt参数)的登录密码
  8. Ubuntu下adb无法识别android设备的解决方法
  9. 塞雷三分钟漫画中国史4
  10. 2023年软考初级程序员