(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多路复用原理的更多相关文章

  1. IO多路复用原理&场景

    目录 IO多路复用的历史 阻塞 IO 非阻塞 IO IO 多路复用 select poll epoll IO多路复用高效的原因 IO多路复用解决的什么问题 epoll比selector性能一定更好吗 ...

  2. 理论铺垫:阻塞IO、非阻塞IO、IO多路复用/事件驱动IO(单线程高并发原理)、异步IO

    完全来自:http://www.cnblogs.com/alex3714/articles/5876749.html 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同 ...

  3. socket_server源码剖析、python作用域、IO多路复用

    本节内容: 课前准备知识: 函数嵌套函数的使用方法: 我们在使用函数嵌套函数的时候,是学习装饰器的时候,出现过,由一个函数返回值是一个函数体情况. 我们在使用函数嵌套函数的时候,最好也这么写. def ...

  4. python之IO多路复用

    在python的网络编程里,socetserver是个重要的内置模块,其在内部其实就是利用了I/O多路复用.多线程和多进程技术,实现了并发通信.与多进程和多线程相比,I/O多路复用的系统开销小,系统不 ...

  5. IO多路复用的几种实现机制的分析

    http://blog.csdn.net/zhang_shuai_2011/article/details/7675797 select,poll,epoll都是IO多路复用的机制.所谓I/O多路复用 ...

  6. 转一贴,今天实在写累了,也看累了--【Python异步非阻塞IO多路复用Select/Poll/Epoll使用】

    下面这篇,原理理解了, 再结合 这一周来的心得体会,整个框架就差不多了... http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架, ...

  7. I/O模型系列之五:IO多路复用 select、poll、epoll

    IO多路复用之select.poll.epoll IO多路复用:通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. 应用:适用于针 ...

  8. IO多路复用和local概念

    一.local 在多个线程之间使用threading.local对象,可以实现多个线程之间的数据隔离 import time import random from threading import T ...

  9. 异步、非阻塞和IO多路复用总结

    Nginx是并发处理框架的代表者,很多后台业务都会放在Nginx容器中运行,以实现高吞吐,而Nginx能够支持高并发也是由于使用了异步非阻塞处理模型,本文将用通俗的话讲解异步.同步.阻塞.非阻塞的区别 ...

随机推荐

  1. form表单序列化serialize-object.js

    <form class="form-horizontal" role="form" id="myform" action=" ...

  2. 大数据框架hadoop的序列化机制

    Java内建序列化机制 在Windows系统上序列化的Java对象,可以在UNIX系统上被重建出来,不需要担心不同机器上的数据表示方法,也不需要担心字节排列次序. 在Java中,使一个类的实例可被序列 ...

  3. windows2008 安装oracle10g“程序异常终止。发生内部错误。请将以下文件提供给oracle技术支持部门

    在安装oracle10g客户端程序的时候发生了错误!错误如下:“程序异常终止.发生内部错误.请将以下文件提供给oracle技术支持部门:“未知”“未知”“未知” 解决办法: 右键点setup.exe ...

  4. Guid.NewGuid().ToString()生成唯一码js

    Guid.NewGuid().ToString() 生成唯一码,用户生成随机id 生成唯一编码,版本控制对比等. //表示全局唯一标识符 (GUID). function Guid(g) { var ...

  5. PHP实现IMAP

    //以腾讯企业邮箱做了测试 $mailServer="imap.exmail.qq.com"; //IMAP主机 $mailLink="{{$mailServer}:14 ...

  6. Linux 开发环境搭建与使用——SlickEdit 的安装与配置

    SlickEdit 的介绍 vim 是公认很好用很完美,但是对新手来说,上手毕竟不是很容易.Windows 下程序员很多都很喜欢Source Insight 这个工具来看代码,各种语法高亮看着很舒服. ...

  7. bzoj 3119: Book

    Description Wayne喜欢看书,更喜欢买书.某天Wayne在当当网上买书,买了很多很多书.Wayne有一个奇怪的癖好,就是第一本书的价格必须恰为X,而之后买的每一本书,若是比上一本更昂贵, ...

  8. MySQL 数据库查询练习

    -- ---------------------------- -- mysql练习sql脚本 -- ---------------------------- create database db10 ...

  9. c#二维码建立与识别

    QrCodeEncodingOptions options = new QrCodeEncodingOptions(); options.CharacterSet = "UTF-8" ...

  10. spring错误处理 Build path is incomplete. Cannot find class file for org.springframework.aop.Advisor

    Build path is incomplete. Cannot find class file for org.springframework.aop.Advisor 初学spring,记录一下出现 ...