并发式IO的解决方案:多路非阻塞式IO、多路复用、异步IO
在Linux应用编程中的并发式IO的三种解决方案是:
(1) 多路非阻塞式IO
(2) 多路复用
(3) 异步IO
以下代码将以操作鼠标和键盘为实例来演示。
1. 多路非阻塞式IO
多路非阻塞式IO访问,主要是添加O_NONBLOCK标志和fcntl()函数。
代码示例:
/*
* 并发式IO的解决方案1:多路非阻塞式IO处理键盘和鼠标同时读取
*/ #include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h> #define MOUSEPATH "/dev/input/mouse1" int main(void)
{
int fd = -;
int ret = -;
int flag = -;
char buf[] = {}; fd = open(MOUSEPATH, O_RDONLY | O_NONBLOCK);
if (fd < )
{
perror("open");
_exit(-);
} // 把0的文件描述符变成非阻塞式的
flag = fcntl(, F_GETFD); // 获取stdin原来的flag
flag |= O_NONBLOCK; // 给stdin原来的flag添加非阻塞式属性
fcntl(, F_SETFL, flag); // 更新flag while ()
{
// 读鼠标
memset(buf, , sizeof(buf));
ret = read(fd, buf, ); if (ret > )
{
printf("鼠标读出的内容是:[%s]\n", buf);
} // 读键盘
memset(buf, , sizeof(buf));
ret = read(, buf, );
if (ret > )
{
printf("键盘读出的内容是:[%s]\n", buf);
}
} return ;
}
2. IO多路复用
(1) 多路非阻塞式IO
(2) select() 和 poll() 函数
(3) 外部式阻塞,内部非阻塞式自动轮询多路阻塞式IO
代码示例:
select() 函数实现:
/*
* 并发式IO的解决方案2:多路复用select()函数处理
*/ #include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <stdlib.h> #define MOUSEPATH "/dev/input/mouse1" int main(void)
{
int fd = -, ret = -;
char buf[] = {};
fd_set myset;
struct timeval tmv; fd = open(MOUSEPATH, O_RDONLY);
if (- == fd)
{
perror("open");
_exit(-);
} // 处理myset
FD_ZERO(&myset); // 清零
FD_SET(fd, &myset); // 加载鼠标的文件描述符到myset集合中
FD_SET(, &myset); // struct timeval *timeout 超时处理
tmv.tv_sec = ;
tmv.tv_usec = ; // 原型:int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
ret = select(fd+, &myset, NULL, NULL, &tmv); // fd+1 这里是最大的fd加1 nfds是从0开始的
if (ret < )
{
perror("select");
_exit(-);
}
else if (ret == )
{
printf("Timeout.\n");
exit();
}
else
{
/* 等到了一路IO,然后去监测哪个IO到了就处理哪个IO */
if ( FD_ISSET(fd, &myset) )
{
// 这里处理鼠标
memset(buf, , sizeof(buf));
read(fd, buf, );
printf("鼠标读出的内容是:[%s]\n", buf);
} if ( FD_ISSET(, &myset) )
{
// 这里处理键盘
memset(buf, , sizeof(buf));
read(, buf, );
printf("键盘读出的内容是:[%s]\n", buf);
}
} return ;
}
poll() 函数实现:
/*
* 并发式IO的解决方案2:多路复用poll()函数处理
*/ #include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#include <stdlib.h> #define MOUSEPATH "/dev/input/mouse1"
#define IO_MULTIPLEXING 2
#define MAXBUF 1024
#define MILLISECOND 1000 int main(void)
{
int fd = -, ret = -, i = ;
char buf[MAXBUF] = {};
struct pollfd pfd[IO_MULTIPLEXING] = {}; fd = open(MOUSEPATH, O_RDONLY);
if (- == fd)
{
perror("open");
_exit(-);
} // 初始化 pollfd
pfd[].fd = ; // 键盘
pfd[].events = POLLIN; // 等待读操作 pfd[].fd = fd; // 键盘
pfd[].events = POLLIN; // 等待读操作 // 原型:int poll(struct pollfd *fds, nfds_t nfds, int timeout);
ret = poll(pfd, fd+, * MILLISECOND); // fd+1 这里是最大的fd加1 nfds是从0开始的
if (ret < )
{
perror("poll");
_exit(-);
}
else if (ret == )
{
printf("Timeout.\n");
exit();
}
else
{
/* 等到了一路IO,然后去监测哪个IO到了就处理哪个IO */
for (i = ; i < IO_MULTIPLEXING; i++)
{
// 处理键盘和鼠标
if ( pfd[i].events == pfd[i].revents )
{
memset(buf, , sizeof(buf));
read(pfd[i].fd, buf, MAXBUF);
printf("Content:[%s].\n", buf);
}
}
} close(fd); return ;
}
3. 异步IO
(1) 异步IO:就是操作系统用软件实现的一套中断响应系统
(2) 工作方法:进程注册一个异步IO事件(使用signal注册一个信号SIGIO的处理函数)
(3) 涉及函数:fcntl(F_GETFL, F_SETFL, O_ASYNC, F_SETOWN), signal(), sigaction()函数
代码示例:
/*
* 并发式IO的解决方案3:异步IO处理 signal or sigaction and fcntl
*/ #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <string.h> #define MAXBUFF 1024
#define MOUSEPATH "/dev/input/mouse1" // 全局变理
int mousefd = -; // 定义signal的函数指针
typedef void (*sighandler_t)(int); // 函数声明
void func(int sig); int main(void)
{
int flag = -;
char buf[MAXBUFF];
sighandler_t ret = (sighandler_t)-; // 操作鼠标文件
mousefd = open(MOUSEPATH, O_RDONLY);
if ( mousefd < )
{
perror("open");
_exit(-);
} // 把鼠标的文件描述符设置为可以接受异步IO
flag = fcntl(mousefd, F_GETFL);
flag |= O_ASYNC;
fcntl(mousefd, F_SETFL, flag); // 把异步IO事件的接收进程设置为当前进程
fcntl(mousefd, F_SETOWN, getpid()); // 注册当前进程的SIGIO信号捕获函数
ret = signal(SIGIO, func);
if (SIG_ERR == ret)
{
perror("signal");
_exit(-);
} // 操作键盘
while ()
{
memset(buf, , sizeof(buf));
read(, buf, MAXBUFF);
printf("键盘读取的内容是:[%s].\n", buf);
} return ;
} // 绑定到SIGIO信号,在函数内处理异步通知事件
void func(int sig)
{
char buf[MAXBUFF] = {}; if ( sig != SIGIO )
return; read(mousefd, buf, MAXBUFF);
printf("鼠标读取的内容是:[%s].\n", buf);
}
并发式IO的解决方案:多路非阻塞式IO、多路复用、异步IO的更多相关文章
- 阻塞、非阻塞、同步、异步IO
阻塞.非阻塞.同步.异步IO http://www.cnblogs.com/yunxitalk/p/9031306.html 介绍 在谈及网络IO的时候总避不开阻塞.非阻塞.同步.异步.IO多路复用. ...
- Java IO(3)非阻塞式输入输出(NIO)
在上篇<Java IO(2)阻塞式输入输出(BIO)>的末尾谈到了什么是阻塞式输入输出,通过Socket编程对其有了大致了解.现在再重新回顾梳理一下,对于只有一个“客户端”和一个“服务器端 ...
- 一文读懂阻塞、非阻塞、同步、异步IO
介绍 在谈及网络IO的时候总避不开阻塞.非阻塞.同步.异步.IO多路复用.select.poll.epoll等这几个词语.在面试的时候也会被经常问到这几个的区别.本文就来讲一下这几个词语的含义.区别以 ...
- Linux NIO 系列(03) 非阻塞式 IO
目录 一.非阻塞式 IO 附:非阻塞式 IO 编程 Linux NIO 系列(03) 非阻塞式 IO Netty 系列目录(https://www.cnblogs.com/binarylei/p/10 ...
- 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型
1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...
- 网络IO之阻塞、非阻塞、同步、异步总结
网络IO之阻塞.非阻塞.同步.异步总结 1.前言 在网络编程中,阻塞.非阻塞.同步.异步经常被提到.unix网络编程第一卷第六章专门讨论五种不同的IO模型,Stevens讲的非常详细,我记得去年看第一 ...
- 阻塞式和非阻塞式IO
有很多人把阻塞认为是同步,把非阻塞认为是异步:个人认为这样是不准确的,当然从思想上可以这样类比,但方式是完全不同的,下面说说在JAVA里面阻塞IO和非阻塞IO的区别 在JDK1.4中引入了一个NIO的 ...
- IO通信模型(二)同步非阻塞模式NIO(NonBlocking IO)
同步非阻塞模式(NonBlocking IO) 在非阻塞模式中,发出Socket的accept()和read()操作时,如果内核中的数据还没有准备好,那么它并不会阻塞用户进程,而是立刻返回一个信息.也 ...
- 磁盘IO的性能指标 阻塞与非阻塞、同步与异步 I/O模型
磁盘IO的性能指标 - 蝈蝈俊 - 博客园https://www.cnblogs.com/ghj1976/p/5611648.html 阻塞与非阻塞.同步与异步 I/O模型 - 蝈蝈俊.net - C ...
随机推荐
- 关于创建可执行的jar文件(assembly)
java利用maven生成一个jar包,如何自动生成清单属性文件(MANIFEST.MF),如何解决jar依赖问题? 办法很简单: 只需在pom.xml文件中配置如下plugin即可: <plu ...
- C# 選擇本機檔案並上傳
參考自:http://www.dotblogs.com.tw/puma/archive/2008/11/07/5910.aspxhttp://www.codeproject.com/Articles/ ...
- CHECK MEMBER TYPE
检查类里是否存在某种类型的几种方法,以检查xxx类型为例:方法1: template<class T> class has_member_type_Type { ]; }; templat ...
- Mac OS X Tips
命令行查看Mac OS X版本 $ sw_vers ProductName: Mac OS X ProductVersion: BuildVersion: 14D131 Mac OS X截图 不要使用 ...
- JS调用WebService
<html> <title>接口测试</title> <meta http-equiv="Content-Type" content=&q ...
- 控制反转(Ioc)和依赖注入(DI)
控制反转IOC, 全称 “Inversion of Control”.依赖注入DI, 全称 “Dependency Injection”. 面向的问题:软件开发中,为了降低模块间.类间的耦合度,提倡基 ...
- python 字符串复制
通过变量来进行赋值 fstr = 'strcpy'sstr = fstrfstr = 'strcpy2'print sstr
- 自定义ISPF面板
1)登录的时候可以看到登录执行的PROCEDURE,此处为DBSPROC 2.登录后,进入SDSF,再进入LOG,输入命令TOP,再输入命令F JOB,按F11把屏幕向右翻页,看到哪下界面 找到//I ...
- Entity Framework Code First ---EF Power Tool MySql
关于如何使用EF Power Tool的介绍请看 http://www.cnblogs.com/LingzhiSun/archive/2011/05/24/EFPowerTool_1.html, 这里 ...
- HTML5 新特性总结
1.使用autocomplete 自动完成必须给input 加上name. 2.SVG图形代码 复制https://developer.mozilla.org/zh-CN/docs/Web/SVG/E ...