企业网站开发实训过程与内容,吉林电商网站建设,黑河网站建设,反向链接查询今天分享的是几种实现并发式IO的方法。什么是并发式IO呢#xff1f;可以简单理解为比如要同时读取几个文件的数据#xff0c;但是这些文件什么时候可以读取是不确定的#xff0c;要实现当某个文件可以读取的时候就立马去读取#xff0c;这就是并发式。首先提出一个问题可以简单理解为比如要同时读取几个文件的数据但是这些文件什么时候可以读取是不确定的要实现当某个文件可以读取的时候就立马去读取这就是并发式。首先提出一个问题如果我们需要读取键盘和鼠标的信息当键盘有按下的时候把按下的内容读取出来并且打印到屏幕上当鼠标有动静的时候也把鼠标的设备文件读取出来该怎么实现呢首先想到的就是在主函数里写个while(1)挨个去读就行了伪代码如下//伪代码while(1){ read(keyboard); printf(keyboard...); read(mouse); printf(mouse...);}这样的程序确实可以读取键盘和鼠标的内容并且打印出来但是必须老老实实按照代码里的先读键盘再读鼠标这样往复如果用户想要先读鼠标再读键盘抱歉它会卡在前面这个read这里因为read函数是阻塞式的没有读到东西它就一直卡在那里。这显然不是我们希望的我们希望像按键盘就按键盘想动鼠标就动鼠标并且它都能打印出来。于是有了以下几种方法来解决这个问题。一、以非阻塞的方式来打开文件在使用open函数的时候加上O_NONBLOCK属性变为非阻塞而标准输入一开始就打开了对应文件描述符为0所以不能用上面的方法应该用fcntl函数来添加。变为非阻塞式的好处就是当read没有读到什么东西的时候会立马返回不会卡在那里。代码如下#include #include #include #include #include #include #define pathname /dev/input/miceint main(){ int fd; int ret; char buf[100]{0}; fdopen(pathname,O_RDWR | O_NONBLOCK); if(fd0) { perror(open failed); return 0; } flag fcntl(0, F_GETFL); // 先获取原来的flag flag | O_NONBLOCK; // 添加非阻塞属性 fcntl(0, F_SETFL, flag); // 更新flag while(1) { memset(buf,0,sizeof(buf)); ret read(fd,buf,50); //读鼠标 // if(ret0) // { // printf(read mouse ret%d\n,ret); // perror(read mouse failed); // // return 0; // } if(ret0) { printf(读出的鼠标内容是[%s]\n,buf); } memset(buf,0,sizeof(buf)); ret read(0,buf,5); //读键盘 // if(ret0) // { // perror(read keyboard failed); // printf(read keyboard ret%d\n,ret); // // return 0; // } if(ret0) { printf(读出的键盘内容是[%s]\n,buf); } } return 0;}上面的代码其实就实现了不管是按下键盘还是点击鼠标都能及时反应打印出数据。但是还有更好的方法使用系统里带的select函数或者是poll函数来监听IO的状况。二、使用select函数或者poll函数select函数和poll函数功能上差不多是Unix两个不同的派系衍生出来的函数后来linux把它们都吸收了。select函数在上一节使用到了可以回顾一下Linux笔记(11)| 网络编程之自己动手写一个服务器和客户端select函数首先把把要监听的文件描述符fd添加到一个集合里面然后调用select函数去监听通过返回值可以判断监听的fd的状态比如已经可写了、或者是可读了。代码如下#include #include #include #include #include #include #include #include #define pathname /dev/input/miceint main(void){ int ret; int fd; char buf[200]; struct timeval tv; tv.tv_sec 5; tv.tv_usec 0; fd_set myset; fdopen(pathname,O_RDONLY); if(fd0) { perror(open mice failed); return 0; } while(1) { FD_ZERO(myset); FD_SET(0, myset); FD_SET(fd, myset); retselect(fd1,myset,NULL,NULL,NULL); if(ret0) { perror(select); return 0; } else if(ret0) { printf(time out\n); sleep(2); } else { if( FD_ISSET(fd,myset)) { memset(buf,0,sizeof(buf)); read(fd,buf,5); printf(读鼠标[%s]\n,buf); } if(FD_ISSET(0,myset)) { memset(buf,0,sizeof(buf)); read(0,buf,5); printf(读键盘[%s]\n,buf); } } } return 0;}poll函数实现的功能差不多只是用法上有些不一样这里直接把代码贴上#include #include #include #include #include #include #include #define pathname /dev/input/miceint main(void){ int fd; int ret; char buf[100]; struct pollfd mypoll[2]{0}; fdopen(pathname,O_RDONLY); if(fd0) { perror(open failed); return 0; } while(1) { mypoll[0].fd0; mypoll[0]. eventsPOLLIN; mypoll[1].fdfd; mypoll[1]. eventsPOLLIN; retpoll(mypoll,fd1,10000); if(ret0) { perror(poll); return 0; } else if(ret0) { printf(time out\n); } else { // printf(mypoll.revents%d\n,mypoll.revents); // printf(mypoll.events%d\n,mypoll.events); if(mypoll[0].reventsmypoll[0].events) { memset(buf,0,sizeof(buf)); retread(0,buf,10); if(ret0) { perror(read keyboard failed ); return 0; } printf(read keyboard:[%s],buf); } if(mypoll[1].reventsmypoll[1].events) { memset(buf,0,sizeof(buf)); retread(fd,buf,2); if(ret0) { perror(read mouse failed ); return 0; } printf(read mouse:[%s]\n,buf); //这里没加换行就不会及时打印 } } } return 0;}三、使用异步IO第三种方法就是使用异步IO这种方法类似于中断就是在主函数里来处理鼠标(或者键盘也一样)然后注册一个异步IO事件当有键盘按下的时候产生一个异步IO信号这个信号就会触发一个注册号的函数来处理它。代码如下#include #include #include #include #include #include #include #include typedef void (*sighandler_t)(int);#define pathname /dev/input/micevoid handler(int sig);char buf[200]; int fd;int main(void){ int flag; int ret; fdopen(pathname,O_RDONLY); if(fd0) { perror(open failed); return 0; } // 把鼠标的文件描述符设置为可以接受异步IO flagfcntl(fd,F_GETFL); flag|O_ASYNC; fcntl(fd,F_SETFL,flag); // 把异步IO事件的接收进程设置为当前进程 fcntl(fd,F_SETOWN,getpid()); // 注册当前进程的SIGIO信号捕获函数 signal(SIGIO,handler); while(1) { memset(buf,0,sizeof(buf)); retread(0,buf,10); // if(ret0) // { // perror(read failed); // return 0; // } if(ret0) printf(read keyboard :[%s]\n,buf); //sleep(2); } return 0;}void handler(int sig){ int ret; if(sig!SIGIO) return; memset(buf,0,sizeof(buf)); retread(fd,buf,5); if(ret0) { perror(read failed); return ; } printf(read mouse :[%s]\n,buf);}以上是今天分享的几种方法实际上还可以用多进程或者多线程的方法这在上一节里也有涉及这里就不多说了。猜你喜欢Linux笔记(11)| 网络编程之自己动手写一个服务器和客户端基于红外传输的多点温度采集系统教你如何用蜂鸣器演奏乐谱