IO模型(阻塞,非阻塞,多路复用......)
1、IO分类
阻塞IO:在进行IO操作的时候,如果资源没有准备就绪,会阻塞等待资源,如果资源准备就绪,获取资源。 常用、简单、效率很低 非阻塞IO:在进行IO操作的时候,如果资源没有准备就绪,返回错误信息,如果资源就绪,获取资源。 任务不会阻塞、轮询访问,CPU的消耗较大。 IO多路复用:将所有操作的IO放到一个集合中,检测集合中准备就绪的IO,然后进行IO操作。 允许同时对多个IO进行操作。 信号驱动IO:资源准备就绪的时候,由内核向任务发送SIGIO信号,任务接收到信号后,去进行IO操作。
2、阻塞IO
资源没有准备就绪,会一直等待常用的有fgets、read、write、accept......
3、非阻塞IO
应用程序在执行的时候告诉系统,如果资源准备就绪,返回资源,如果没有准备就绪,返回错误信息。 实现方式更多采用轮询(polling)具体实现步骤:1) 需要将IO设置为非阻塞模式;a, 打开的时候以非阻塞方式去得到;open(pathname, O_NONBLOCK | O_RDWR);b,在得到IO的文件描述符后,可以去设置。#include <unistd.h>#include <fcntl.h>int fcntl(int fd, int cmd, ... /* arg */ );参数:参数1:fd表示文件描述符参数2:int cmd, ... /* arg */ 是可变参数,返回值:成功:F_GETFL Value of file status flags.F_SETFL 0;失败返回-1,且修改errno的值。
4、IO多路复用
如果现在我来同时操作多个IO:1) 采用阻塞模式,IO的操作顺序由代码决定,多个IO是依次执行; 只要前面的IO没有执行,后面的IO即使资源准备就绪,也不会执行。达不到预期效果(谁准备就绪就执行谁);2) 非阻塞IO模式,多个IO需要进行轮询访问,导致CPU的消耗很大。不利于执行其它任务。3) 采用多任务的方式: 多进程,每一个任务创建一个进程,这个进程会有独立4g内存空间,通信比较麻烦。 多线程,资源共享,需要解决资源互斥和线程的同步。IO多路复用的思路:1) 先创建一个文件描述符集合,将所要关心事件的描述符添加到集合中;2) 调用函数来检测集合,检测是否有准备就绪的事件,有事件准备就绪函数返回,没有事件准备就绪函数阻塞3) 得到准备就绪事件的文件描述符4) 对准备就绪的文件描述符进行IO操作。具体实现机制:1. select机制:将关注的IO操作放到一个集合中,通过select函数实现阻塞遍历,当关注的文件描述符有对应的资源准备就绪,select函数就会返回,返回值代表资源准备就绪的个数,所以需要通过循环遍历判断是哪一种资源准备就绪。select函数每次检测都是从0~1023遍历。集合总共128字节。编程流程:1、创建集合2、清空集合3、将关注的文件描述符逐个加入集合4、select经数阻塞检测资源是否就绪5、循环遍历检测对应的资源6、做对应资源相关的操作7、回到第4步(用一个while循环)1) 函数接口:/* According to POSIX.1-2001 */#include <sys/select.h>/* According to earlier standards */#include <sys/time.h>#include <sys/types.h>#include <unistd.h>int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);参数:参数1:nfds表示的是集合中最大文件描述符+1;参数2:readfds表示关心的读事件集合,不关心用NULL填充参数3:writefds表示关心的写事件集合,不关心用NULL填充参数4:exceptfds表示关心的其它事件集合,不关心用NULL填充参数5:timeout用来设置阻塞事件a, 设置为NULL,表示检测时一直阻塞,直到有事件准备就绪函数才返回b, 设置结构体的值struct timeval {long tv_sec; /* seconds */long tv_usec; /* microseconds */};1) 成员的值都0,非阻塞方式检测;2) 成员值为非零,有阻塞时间。返回值:成功返回值准备就绪事件的个数;返回0表示检测超时失败返回-1,且修改errno的值。void FD_CLR(int fd, fd_set *set); /* 将文件描述符fd从集合set中移除 */int FD_ISSET(int fd, fd_set *set); /* 检测文件描述符fd是否在集合set,如果在返回非0,不在返回0 */void FD_SET(int fd, fd_set *set); /* 将文件描述符fd添加到集合set中 */void FD_ZERO(fd_set *set); /* 清空集合set */2) 具体实现的思路:a,创建读事件集合readfds,并清空集合fd_set readfds;FD_ZERO(&readfds);b,将文件描述符listenfd添加到读事件集合readfds中;FD_SET(listenfd, &readfds);c,检测集合中是否有准备就绪的事件(阻塞方式检测,有事件准备就绪函数返回)ret = select(nfds, &readfds, NULL, NULL, NULL);d,得到准备就绪事件的文件描述符for(fd = 0; fd < nfds; fd++) {if (FD_ISSET(fd, &readfds)) {e,对fd进IO操作。}}3) 特征:a,可以在一个任务中对多个阻塞io进程操作,谁先准备就绪,就操作谁。b,如果操作事件不同,需要定义多个集合;c,找到准备就绪的文件描述符的时候,需要从0遍历到最大的文件描述符。效率很低。
4.1示例代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous *//* 定义服务器初始化函数 */
int server_init(char *ip, short port)
{int ret;int listenfd;struct sockaddr_in srvaddr;/* 创建套接字文件 */listenfd = socket(AF_INET, SOCK_STREAM, 0);if (listenfd == -1) {perror("server_init->socket");return -1;}printf("listenfd = %d\n", listenfd);/* 绑定服务器的ip地址和端口号 */memset(&srvaddr, 0, sizeof(srvaddr));srvaddr.sin_family = AF_INET;srvaddr.sin_port = htons(port);if (ip == NULL)srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);elsesrvaddr.sin_addr.s_addr = inet_addr(ip);ret = bind(listenfd, (const struct sockaddr *)&srvaddr, sizeof(srvaddr));if (ret == -1) {perror("server_init->bind");return -1;}printf("bind success\n");/* 启动监听 */ret = listen(listenfd, 1024);if (ret == -1) {perror("server_init->listen");return -1;}return listenfd;
}/* 定义服务器等待客户端的连接请求,建立连接 */
int server_wait_client_connect(int listenfd)
{int connfd;socklen_t addrlen;struct sockaddr_in cltaddr;//accept(listenfd, NULL, NULL);addrlen = sizeof(cltaddr);connfd = accept(listenfd, (struct sockaddr *)&cltaddr, &addrlen);if (connfd == -1) {perror("accept");return -1;}printf("IP : %s connet success connfd = %d\n", inet_ntoa(cltaddr.sin_addr), connfd);return connfd;
}int main()
{int ret;int listenfd;int connfd;char buf[256];fd_set readfds;fd_set rdfds;int nfds;int fd;/* 1. 服务器的初始化 */listenfd = server_init("127.0.0.1", 8888);//listenfd = server_init(NULL, 8888);if (listenfd == -1)exit(EXIT_FAILURE);printf("server init success\n");/* 创建集合,清空集合 */FD_ZERO(&readfds);/* 将文件描述符listenfd添加到读事件集合readfds中 */FD_SET(listenfd, &readfds);nfds = listenfd + 1;while(1) {/* c, 调用select函数,检测是否有准备就绪的事件,如果没有事件准备就绪,函数一直阻塞。如果有事件准备就绪函数返回;*/rdfds = readfds;ret = select(nfds, &rdfds, NULL, NULL, NULL);if (ret == -1) {perror("select");return -1;}for (fd = 0; fd < nfds; fd++) {/* 找到准备就绪事件的文件描述符 */if (!FD_ISSET(fd, &rdfds))continue;/* 准备就绪事件,进行IO操作 */if (fd == listenfd) { /* 监听套接字 *//* 2. 服务器等待客户端的连接请求,建立连接 */connfd = server_wait_client_connect(listenfd);if (connfd == -1)exit(EXIT_FAILURE);/* 连接成功,将文件描述符connfd添加到读事件集合readfds中 */FD_SET(connfd, &readfds);nfds = (connfd >= nfds ? connfd+1 : nfds);continue;} //if (fd == listenfd) end/* 通信套接字 *//* 3. 服务器处理客户端的数据请求,并处理数据,反馈处理结果 */memset(buf, 0, sizeof(buf));ret = read(fd, buf, sizeof(buf));if (ret == -1) {perror("server->read");return -1;} else if (ret == 0) {/* 客户端退出的时候,需要将套接字从集合中删除 */FD_CLR(fd, &readfds);close(fd);break;}printf("buf : %s\n", buf);ret = write(fd, buf, sizeof(buf));if (ret == -1) {perror("server->write");return -1;}} //for (fd = 0; fd < nfds; fd++) end} //while(1) endreturn 0;
}
IO模型(阻塞,非阻塞,多路复用......)相关推荐
- IO模型之非阻塞IO
1. IO模型非阻塞 IO Linux下,可以通过设置socket使其变为 non-blocking.当对一个non-blocking socket执行读操作时,流程是这个样子: 从图中可以看出,当用 ...
- 五种IO模型:阻塞/非阻塞/复用/信号驱动/异步IO模型
五种IO模型:阻塞/非阻塞/复用/信号驱动/异步IO模型 1. IO基本概念 1.1 IO概念 1.2 IO的两个阶段 1.2.1 IO的两个阶段-例子说明 1.2 IO种类 2. 五种IO模型 2. ...
- I/O: 阻塞非阻塞I/O 同步异步I/O
我们知道,在Linux(UNIX)操作系统中,共有五种IO模型,分别是:阻塞IO模型.非阻塞IO模型.IO复用模型.信号驱动IO模型以及异步IO模型. 同步IO模型 阻塞IO模型 我们钓鱼的时候,有一 ...
- Java网络编程------IO模型的同步/异步/阻塞/非阻塞(1)
IO模型的同步/异步/阻塞/非阻塞 一.同步/异步/阻塞/非阻塞 1.同步和异步 2.阻塞和非阻塞 3.同步.异步和阻塞.非阻塞组合 二.IO 1.I/O 2.阻塞IO和非阻塞IO 3.同步IO和同步 ...
- 异步就是异步,根本就没有 异步非阻塞IO这个说法。阻塞 非阻塞,同步I/O 异步I/O 的区别
先给大家安利一下这个 https://www.ibm.com/developerworks/cn/linux/l-async/ 里面关于 异步非阻塞IO 是错的. 异步就是异步,别扯 异步阻塞 异步非 ...
- 面试必会系列 - 5.1 网络BIO、NIO、epoll,同步/异步模型、阻塞/非阻塞模型,你能分清吗?
本文已收录至 Github(MD-Notes),若博客中图片模糊或打不开,可以来我的 Github 仓库,包含了完整图文:https://github.com/HanquanHq/MD-Notes,涵 ...
- AIO,BIO,NIO:同步阻塞式IO,同步非阻塞IO,异步非阻塞IO
BIO,同步阻塞式IO,简单理解:一个连接一个线程 NIO,同步非阻塞IO,简单理解:一个请求一个线程 AIO,异步非阻塞IO,简单理解:一个有效请求一个线程 IO:阻塞IO BIO:同步阻塞IO.服 ...
- 两段文章清楚弄明白什么是异步IO、同步IO、同步阻塞IO、同步非阻塞IO、异步阻塞IO、异步非阻塞IO
百科解释:异步IO_百度百科 先看2,再看1,会理解的更好! 1. 2.阻塞和非阻塞 # 阻塞和非阻塞关注的是程序在等待调用结果时的状态 # 阻塞调用是指调用结果返回之前,当前线程会被挂起.调用线程只 ...
- java nio io复用_java 非阻塞IO-java NIO-嗨客网
Java的NIO教程 NIO 官方名称叫做 New IO,在 JDK 1.4 中相对于 BIO 的新 IO.但是也有很多人称之为 NON-BLOCKING IO.和 BIO 比较的话,叫做非阻塞 IO ...
- 同步异步阻塞非阻塞杂记
版权声明:本文可能为博主原创文章,若标明出处可随便转载. https://blog.csdn.net/Jailman/article/details/78498458 gevent实现的协程是同步非阻 ...
最新文章
- 拒绝加班,办公电脑换新低至¥1999
- php 经纬度 摩卡 转换,WGS84经纬度坐标与WEB摩卡托坐标转换
- 1103 Integer Factorization (30 分)【难度: 中 / 爆搜】
- 自定义PocketMod的农历页面
- 如何防止插入删除表造成的数据库死锁
- MaxCompute SQL原理解析及性能调优
- “软考”遗失试卷全部追回 相关责任人接受审查
- matlab三角波发生器精度改为定点型,关于matlab simulink中三角波模块的问题!
- x的平方加y平加xy的java语言_面试被虐题:说说 JVM 系语言的函数式编程
- matlab2016b慢,Matlab 2016a/b中调用GPU速度巨慢的解决办法
- 常兴串口调试助手v3.6
- 【高并发】一文解密诡异并发问题的第一个幕后黑手——可见性问题
- 阿波罗登月计算机技术,你知道吗,阿波罗登月用的计算机还不如你家计算器!...
- java调用dll 指针参数_java调用c dll,指针参数和结构体参数搞定
- 雷林鹏最人性化访谈:做投资不仅仅是要赚钱,要成为有价值的人
- 数据结构笔记_34 赫夫曼编码压缩、解压文件
- 我的世界服务器货币充值系统,《我的世界》中国版正式开启了充值功能
- LMS151-10100单线激光雷达与RealSense双目相机的联合标定
- 点到线段直线的距离, 直线与直线的关系 直线与线段的关系
- 用photoshop拼接一个七巧板图案
热门文章
- 【LINUX-python】PATH、sys.path、PYTHONPATH
- 小尺寸android 手机推荐,喜欢小屏安卓手机的来看看,这三款便宜又好用
- esp32入门手册学习
- 五剑同辉 聚力安全:绿盟科技五大安全实验室震撼发布
- 1761:神奇的口袋(2)
- [JS]JSON字符串与JS对象的转换
- 压测、压力测试分析、UV、PV、通用性能提高、并发
- 携程在线网页制作(flex布局)(静态页面)
- 代号斗罗显示服务器暂未开放,代号:斗罗内测版
- 过年烟花特效+鼠标滑过+樱花特效