IO多路复用原理
(1)IO multiplexing
(2)用在什么地方?多路非阻塞式IO。
(3)select和poll
(4)外部阻塞式,内部非阻塞式自动轮询多路阻塞式IO
IO多路复用原理:
其实就是整个函数对外表现为阻塞式的,也就是我们调用这个函数,如果条件达不到一定
会被阻塞;但是其实内部并不是阻塞的,而是以一种非阻塞的方式工作的,内部能够实现
自动轮询,如果有任何一个IO设备达到条件即可返回到应用层。
用select函数实现IO多路复用:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
原理:通过阻塞监听设备文件是否有数据可操作,如果有数据可读则返回,当然也可以设
置超时时间,然后我们通过read函数去读取/写,所以其实这个就不涉及到read函数是否
是阻塞或者是非阻塞的了。因为select函数返回之后才能读取,所以有数据我们就去读取
,没有我们就不去读。
我们可以设置多路的IO操作,当调用select函数的时候进行阻塞,内部轮询监听是否可以
进行相应的操作,如果那个可以进行操作那么就操作哪个,然后返回到应用层去,结束
select函数的阻塞。
参数详解:
第一个参数:其实就是表示多路IO时,文件描述符最大的值+1,因为我们的fd是从0开始
的。
第二个参数:是一个指向fd_set结构体的指针,结构体需要我们通过以下的函数来填充:
void FD_CLR(int fd, fd_set *set); 用来清除描述词组set中相关fd 的位
int FD_ISSET(int fd, fd_set *set); 用来测试描述词组set中相关fd 的位是否为真
void FD_SET(int fd, fd_set *set); 用来设置描述词组set中相关fd的位
void FD_ZERO(fd_set *set); 用来清除描述词组set的全部位
也就是表示在我们打开的所有设备文件中要进行读操作的设备是那些,把他的fd填充进去
,如果所有的都不进行读操作,则写NULL。
第三个参数: 一般是NULL
第四个参数:一般是NULL
第五个参数:表示超时时间(阻塞时间),是一个结构体:如下:
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
有一个秒和一个微秒,是共同配合使用的,xx秒xx微秒
返回值:失败: -1 超时返回 0 成功:> 0
/*************************************************************************/
代码如下:
#include <stdio.h>
//According to POSIX.1-2001
#include <sys/select.h>
//According to earlier standards
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define FILE "/dev/input/mouse0"
int main(void)
{
int fd = -1;
int sele_ret = -1;
fd_set Fd_set;
struct timeval time = {0};
char buf[10] = {0};
//打开设备文件
fd = open(FILE, O_RDONLY);
if (-1 == fd)
{
perror("open error");
exit(-1);
}
//构建多路复用IO
FD_ZERO(&Fd_set); //清除全部fd
FD_SET(0, &Fd_set); //添加标准输入
FD_SET(fd, &Fd_set); //添加鼠标
time.tv_sec = 10; //设置阻塞超时时间为10秒钟
time.tv_usec = 0;
sele_ret = select(fd+1, &Fd_set, NULL, NULL, &time);
if (0 > sele_ret)
{
perror("select error");
exit(-1);
}
else if (0 == sele_ret)
{
printf("无数据输入,等待超时.\n");
}
else
{
if (FD_ISSET(0, &Fd_set)) //监听得到得到的结果若是键盘,则让去读取键盘的数据
{
memset(buf, 0, sizeof(buf));
read(0, buf, sizeof(buf)/2);
printf("读取键盘的内容是: %s.\n", buf);
}
if (FD_ISSET(fd, &Fd_set)) //监听得到得到的结果若是鼠标,则去读取鼠标的数据
{
memset(buf, 0, sizeof(buf));
read(fd, buf, sizeof(buf)/2);
printf("读取鼠标的内容是: %s.\n", buf);
}
}
//关闭鼠标设备文件
close(fd);
return 0;
}
/********************************************************************************/
poll函数实现IO多路复用:
原型:int poll(struct pollfd *fds, nfds_t nfds, int timeout);
参数详解:
第一个参数 :struct pollfd {
int fd; //文件描述符
short events; //请求的事件
short revents; //返回的事件
};
其实就是我们多路复用IO的所有文件的fd,注意这里跟select不一样,他是在这个结构体
内进行区分的, events就是表示我们是进行那种操作,是用宏定义的, revents是内核
构建的,返回一个事件,所以我们就是通过 events == revents来确定是不是该fd发生了
可操作。
宏定义如下:
POLLIN 普通或优先级带数据可读
POLLRDNORM 普通数据可读
POLLRDBAND 优先级带数据可读
POLLPRI 高优先级数据可读
POLLOUT 普通数据可写
POLLWRNORM 普通数据可写
POLLWRBAND 优先级带数据可写
POLLERR 发生错误
POLLHUP 发生挂起
POLLNVAL 描述字不是一个打开的文件
第二个参数:就是select的第一个参数
第三个参数:阻塞超时时间,以毫秒为单位
返回值:跟select是一样的,失败-1 超时0 >0成功
代码如下:
/*****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FILE "/dev/input/mouse0"
int main(void)
{
int fd = -1;
int poll_ret = 0;
struct pollfd poll_fd[2] = {0};
char buf[100] = {0};
//打开设备文件
fd = open(FILE, O_RDONLY);
if (-1 == fd)
{
perror("open error");
exit(-1);
}
//构建多路复用IO
poll_fd[0].fd = 0; //键盘
poll_fd[0].events = POLLIN; //定义请求的事件为读数据
poll_fd[1].fd = fd; //鼠标
poll_fd[1].events = POLLIN; //定义请求的事件为读数据
int time = 10000; //定义超时时间为10秒钟
poll_ret = poll(poll_fd, fd+1, time);
if (0 > poll_ret)
{
perror("poll error");
exit(-1);
}
else if (0 == poll_ret)
{
printf("阻塞超时.\n");
}
else
{
if (poll_fd[0].revents == poll_fd[0].events) //监听得到得到的结果若是键盘,则让去读取键盘的数据
{
memset(buf, 0, sizeof(buf));
read(0, buf, sizeof(buf)/2);
printf("读取键盘的内容是: %s.\n", buf);
}
if (poll_fd[1].revents == poll_fd[1].events) //监听得到得到的结果若是鼠标,则去读取鼠标的数据
{
memset(buf, 0, sizeof(buf));
read(fd, buf, sizeof(buf)/2);
printf("读取鼠标的内容是: %s.\n", buf);
}
}
//关闭文件
close(fd);
return 0;
}
IO多路复用原理的更多相关文章
- IO多路复用原理&场景
目录 IO多路复用的历史 阻塞 IO 非阻塞 IO IO 多路复用 select poll epoll IO多路复用高效的原因 IO多路复用解决的什么问题 epoll比selector性能一定更好吗 ...
- 理论铺垫:阻塞IO、非阻塞IO、IO多路复用/事件驱动IO(单线程高并发原理)、异步IO
完全来自:http://www.cnblogs.com/alex3714/articles/5876749.html 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同 ...
- socket_server源码剖析、python作用域、IO多路复用
本节内容: 课前准备知识: 函数嵌套函数的使用方法: 我们在使用函数嵌套函数的时候,是学习装饰器的时候,出现过,由一个函数返回值是一个函数体情况. 我们在使用函数嵌套函数的时候,最好也这么写. def ...
- python之IO多路复用
在python的网络编程里,socetserver是个重要的内置模块,其在内部其实就是利用了I/O多路复用.多线程和多进程技术,实现了并发通信.与多进程和多线程相比,I/O多路复用的系统开销小,系统不 ...
- IO多路复用的几种实现机制的分析
http://blog.csdn.net/zhang_shuai_2011/article/details/7675797 select,poll,epoll都是IO多路复用的机制.所谓I/O多路复用 ...
- 转一贴,今天实在写累了,也看累了--【Python异步非阻塞IO多路复用Select/Poll/Epoll使用】
下面这篇,原理理解了, 再结合 这一周来的心得体会,整个框架就差不多了... http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架, ...
- I/O模型系列之五:IO多路复用 select、poll、epoll
IO多路复用之select.poll.epoll IO多路复用:通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. 应用:适用于针 ...
- IO多路复用和local概念
一.local 在多个线程之间使用threading.local对象,可以实现多个线程之间的数据隔离 import time import random from threading import T ...
- 异步、非阻塞和IO多路复用总结
Nginx是并发处理框架的代表者,很多后台业务都会放在Nginx容器中运行,以实现高吞吐,而Nginx能够支持高并发也是由于使用了异步非阻塞处理模型,本文将用通俗的话讲解异步.同步.阻塞.非阻塞的区别 ...
随机推荐
- 为什么 Windows 10 无论怎么设置一分钟后就自动关屏幕?
为什么 Windows 10 无论怎么设置一分钟后就自动关屏幕? 在设置中设置了很多方法,但不管怎么设置就是不行,不到一分钟一定关屏幕. 开始以为是能源之星引起,查了相关资料说不是,那个能源之星标志只 ...
- FastAdmin 中 的 layer js 使用 r.js 压缩出现的问题
FastAdmin 中 的 layer js 使用 r.js 压缩出现的问题 https://fly.layui.com/jie/2120/ layer是requirejs压缩文件r.js里面的关键字 ...
- Django的认证系统 auth模块
Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...
- DevExpress GridControl 单元格添加进度条(ProgressBar)
首先可以使用DevExpress GridControl 自带的进度条控件. 但是我要用一个方法来设置所以的单元格进度,而不是每个单元格都要设置一遍,同时我想要根据进度值不同,进度条显示不同的颜色. ...
- form表单序列化serialize-object.js
<form class="form-horizontal" role="form" id="myform" action=" ...
- 【python】使用HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies
一.从HTML文档中提取链接 模块HTMLParser,该模块使我们能够根据HTML文档中的标签来简洁.高效地解析HTML文档. 处理HTML文档的时候,我们常常需要从其中提取出所有的链接.使用HTM ...
- Spring MVC、MyBatis整合文件配置详解
Spring:http://spring.io/docs MyBatis:http://mybatis.github.io/mybatis-3/ Building a RESTful Web Serv ...
- TCL基本语法
所有的Tcl文件都以.tcl为扩展名. #!/usr/bin/tclsh puts "Hello, World!" TCL,我们使用新的行或分号终止代码前行.但分号不是必要的,如果 ...
- J2EE Filter中修改request内容
最近在做一个微信相关的网站,很多地方涉及到微信表情的输入,导致内容无法插入到数据库,虽然有用到一个表情过滤的工具类,但是需要过滤的地方比较多,于是想到在过滤器中过滤用户请求的内容. request这个 ...
- Selenium2+python自动化62-jenkins持续集成环境搭建
前言 selenium脚本写完之后,一般是集成到jenkins环境了,方便一键执行. 一.环境准备 小编环境: 1.win10 64位 2.JDK 1.8.0_66 3.tomcat 9.0.0.M4 ...