在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的更多相关文章

  1. 阻塞、非阻塞、同步、异步IO

    阻塞.非阻塞.同步.异步IO http://www.cnblogs.com/yunxitalk/p/9031306.html 介绍 在谈及网络IO的时候总避不开阻塞.非阻塞.同步.异步.IO多路复用. ...

  2. Java IO(3)非阻塞式输入输出(NIO)

    在上篇<Java IO(2)阻塞式输入输出(BIO)>的末尾谈到了什么是阻塞式输入输出,通过Socket编程对其有了大致了解.现在再重新回顾梳理一下,对于只有一个“客户端”和一个“服务器端 ...

  3. 一文读懂阻塞、非阻塞、同步、异步IO

    介绍 在谈及网络IO的时候总避不开阻塞.非阻塞.同步.异步.IO多路复用.select.poll.epoll等这几个词语.在面试的时候也会被经常问到这几个的区别.本文就来讲一下这几个词语的含义.区别以 ...

  4. Linux NIO 系列(03) 非阻塞式 IO

    目录 一.非阻塞式 IO 附:非阻塞式 IO 编程 Linux NIO 系列(03) 非阻塞式 IO Netty 系列目录(https://www.cnblogs.com/binarylei/p/10 ...

  5. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  6. 网络IO之阻塞、非阻塞、同步、异步总结

    网络IO之阻塞.非阻塞.同步.异步总结 1.前言 在网络编程中,阻塞.非阻塞.同步.异步经常被提到.unix网络编程第一卷第六章专门讨论五种不同的IO模型,Stevens讲的非常详细,我记得去年看第一 ...

  7. 阻塞式和非阻塞式IO

    有很多人把阻塞认为是同步,把非阻塞认为是异步:个人认为这样是不准确的,当然从思想上可以这样类比,但方式是完全不同的,下面说说在JAVA里面阻塞IO和非阻塞IO的区别 在JDK1.4中引入了一个NIO的 ...

  8. IO通信模型(二)同步非阻塞模式NIO(NonBlocking IO)

    同步非阻塞模式(NonBlocking IO) 在非阻塞模式中,发出Socket的accept()和read()操作时,如果内核中的数据还没有准备好,那么它并不会阻塞用户进程,而是立刻返回一个信息.也 ...

  9. 磁盘IO的性能指标 阻塞与非阻塞、同步与异步 I/O模型

    磁盘IO的性能指标 - 蝈蝈俊 - 博客园https://www.cnblogs.com/ghj1976/p/5611648.html 阻塞与非阻塞.同步与异步 I/O模型 - 蝈蝈俊.net - C ...

随机推荐

  1. Til the Cows Come Home(最短路)

    Til the Cows Come Home Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I ...

  2. access里like的通配符不能用%,要用*

    转自http://www.knowsky.com/339881.html access里like的通配符用法是这样:     “?”表示任何单一字符: “*”表示零个或多个字符: “#”表示任何一个数 ...

  3. Probabilistic Graphical Models

    http://innopac.lib.tsinghua.edu.cn/search~S1*chx?/YProbabilistic+Graphical+Models&searchscope=1& ...

  4. 【转】Velocity模板(VM)语言介绍

    http://www.blogjava.net/caizh2009/archive/2010/08/20/329495.html Velocity是什么? Velocity是一个基于java的模板引擎 ...

  5. @media 手机与IPAD与PC

    @media screen and (min-width: 769px) { bindCard{height:28.5em} } @media screen and (min-device-width ...

  6. VS2010打包,遇到的一些问题和解决办法

    我用的VS2010,教程很多,我就不一一介绍了,我把我自己遇到的一些问题向大家说一下: 1 可能我比较笨吧,没有理解网上很多教程的意思,直接把图片的后缀名改了,导致添加快捷方式图标的时候出现这种情况 ...

  7. DDD:Strategic Domain Driven Design with Context Mapping

    Introduction Many approaches to object oriented modeling tend not to scale well when the application ...

  8. rabbitmq使用dead letter机制来进行retry

    首先建立 工作exchange和工作queue,指定工作队列的x-dead-letter-exchange到重试exchenge var workQueueArgs = new Dictionary& ...

  9. java io系列01之 "目录"

    java io 系列目录如下: 01. java io系列01之  "目录" 02. java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括 ...

  10. 自定义能够for each的类,C#,Java,C++,C++/cli的实现方法

    自定义类能够被for each,应该算是个老生常谈的话题了,相关的资料都很多,不过这里整理总结主流语言的不同实现方式,并比较部分细节上的差异. 第一种语言,也是实现起来最简单的Java语言.在Java ...