在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. (笔记)Linux内核学习(五)之中断推后处理机制

    一 中断 硬件通过中断与操作系统进行通信,通过对硬件驱动程序处注册中断处理程序,快速响应硬件的中断. 硬件中断优先级很高,打断当前正在执行的程序.有两种情况: 硬件中断在中断处理程序中处理 硬件中断延 ...

  2. Android数据缓存

    1.http://blog.csdn.net/lnb333666/article/details/8460159 2.https://github.com/Trinea/android-common ...

  3. Windows CMD命令大全(转)

    Windows CMD命令大全   命令简介 cmd是command的缩写.即命令行 . 虽然随着计算机产业的发展,Windows 操作系统的应用越来越广泛,DOS 面临着被淘汰的命运,但是因为它运行 ...

  4. 国内的maven镜像

    阿里云 <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>ht ...

  5. POJ 1631 Bridging signals

    Bridging signals Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9441   Accepted: 5166 ...

  6. mysql 学习碎片

    1.mysql 中执行 sql字符串 set @strSql='select 1200 as item'; prepare select_sql from @strSql; execute selec ...

  7. LevelDB(v1.3) 源码阅读之 Slice

    LevelDB(v1.3) 源码阅读系列使用 LevelDB v1.3 版本的代码,可以通过如下方式下载并切换到 v1.3 版本的代码: $ git clone https://github.com/ ...

  8. wndbg下载与安装

    wndbg分X86和X64两个版本 如果你的程序是32位的,就下载安装X86的版本:如果你的程序是64位,就下载X64版本. x86位版本下载:[微软官方安装版] x64位版本下载:[微软官方安装版]

  9. SVN分支与合并

    分支的基本概念就正如它的名字,开发的一条线独立于另一条线,如果回顾历史,可以发现两条线分享共同的历史,一个分支总是从一个备份开始的,从那里开始,发展自己独有的历史(如下图所示) ⑴创建分支 假设目前我 ...

  10. nginx url自动加斜杠的问题

    nginx url自动加斜杠问题及301重定向 时间:2016-02-04 15:14:28来源:网络 导读:nginx url自动加斜杠问题及301重定向,URL指向一个目录并且在最后没有包含斜杠, ...