以下内容源于朱有鹏《物联网大讲堂》课程的学习整理,如有侵权,请告知删除。

一、并发式IO的解决方案

  • 所谓并发式IO,即上节中提及的鼠标和键盘都已经启动。

1、非阻塞式IO

  • 使用fcntl函数, 将上节中阻塞式的鼠标和键盘读取改为非阻塞式的。
  • 性能不是很好。

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main(void)
{// 读取鼠标int fd = -1;int flag = -1;char buf[200];int ret = -1;fd = open("/dev/input/mouse1", O_RDONLY | O_NONBLOCK);if (fd < 0){perror("open:");return -1;}// 把0号文件描述符(stdin)变成非阻塞式的flag = fcntl(0, F_GETFL);      // 先获取原来的flagflag |= O_NONBLOCK;               // 添加非阻塞属性fcntl(0, F_SETFL, flag);      // 更新flag// 这3步之后,0就变成了非阻塞式的了while (1){// 读鼠标memset(buf, 0, sizeof(buf));ret = read(fd, buf, 50);if (ret > 0){printf("鼠标读出的内容是:[%s].\n", buf);}// 读键盘memset(buf, 0, sizeof(buf));ret = read(0, buf, 5);if (ret > 0){printf("键盘读出的内容是:[%s].\n", buf);}}return 0;
}/*
int main(void)
{// 读取鼠标int fd = -1;char buf[200];fd = open("/dev/input/mouse1", O_RDONLY | O_NONBLOCK);if (fd < 0){perror("open:");return -1;}memset(buf, 0, sizeof(buf));printf("before read.\n");read(fd, buf, 50);printf("读出的内容是:[%s].\n", buf);return 0;
}
*//*
int main(void)
{// 读取键盘// 键盘就是标准输入,stdinchar buf[100];int flag = -1;// 把0号文件描述符(stdin)变成非阻塞式的flag = fcntl(0, F_GETFL);      // 先获取原来的flagflag |= O_NONBLOCK;               // 添加非阻塞属性fcntl(0, F_SETFL, flag);      // 更新flag// 这3步之后,0就变成了非阻塞式的了memset(buf, 0, sizeof(buf));printf("before read.\n");read(0, buf, 5);printf("读出的内容是:[%s].\n", buf);return 0;
}
*/

2、多路复用IO

3、异步通知(异步IO)

二、IO多路复用原理

1、何为IO多路复用?

(1)英文为:IO multiplexing

(2)用在什么地方?

  • 用于解决并发式IO,多路阻塞式的。

(3)涉及select函数、poll函数。

  • 两个函数设计思想一样,外部特征不一样。

(4)实现原理:外部阻塞式(select函数本身是阻塞式的),内部非阻塞式自动轮询(select自动轮询时A,B)多路阻塞式IO(键盘A,鼠标B,这两者本身是阻塞式的)。

  • 只要AB至少有一个输入,则select由阻塞返回。

2、select函数介绍

3、poll函数介绍

4、多路复用实践

(1)用poll函数实现同时读取键盘鼠标

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>int main(void)
{// 读取鼠标int fd = -1, ret = -1;char buf[200];struct pollfd myfds[2] = {0};fd = open("/dev/input/mouse1", O_RDONLY);if (fd < 0){perror("open:");return -1;}// 初始化我们的pollfdmyfds[0].fd = 0;        // 键盘myfds[0].events = POLLIN; // 等待读操作myfds[1].fd = fd;      // 鼠标myfds[1].events = POLLIN; // 等待读操作ret = poll(myfds, fd+1, 10000);if (ret < 0){perror("poll: ");return -1;}else if (ret == 0){printf("超时了\n");}else{// 等到了一路IO,然后去监测到底是哪个IO到了,处理之if (myfds[0].events == myfds[0].revents){// 这里处理键盘memset(buf, 0, sizeof(buf));read(0, buf, 5);printf("键盘读出的内容是:[%s].\n", buf);}if (myfds[1].events == myfds[1].revents){// 这里处理鼠标memset(buf, 0, sizeof(buf));read(fd, buf, 50);printf("鼠标读出的内容是:[%s].\n", buf);}}return 0;
}

(2)用select函数实现同时读取键盘鼠标

  • 设置超时时间,即阻塞的时间不能太长,如果很久都没有IO来激活select,则表明超时了。

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>int main(void)
{// 读取鼠标int fd = -1, ret = -1;char buf[200];fd_set myset;struct timeval tm;//设置超时时间,即阻塞的时间不能太长,如果很久都没有IO来激活select,则表明超时了。fd = open("/dev/input/mouse1", O_RDONLY);if (fd < 0){perror("open:");return -1;}// 当前有2个fd,一共是fd一个是0// 处理mysetFD_ZERO(&myset);FD_SET(fd, &myset);FD_SET(0, &myset);tm.tv_sec = 10;tm.tv_usec = 0;ret = select(fd+1, &myset, NULL, NULL, &tm);//+1,是因为0~fd,则共有fd+1个文件描述符if (ret < 0)//错误{perror("select: ");return -1;}else if (ret == 0)//表明超时{printf("超时了\n");}else//>0表示有一路IO激活了{// 等到了一路IO,然后去监测到底是哪个IO到了,处理之if (FD_ISSET(0, &myset)){// 这里处理键盘memset(buf, 0, sizeof(buf));read(0, buf, 5);printf("键盘读出的内容是:[%s].\n", buf);}if (FD_ISSET(fd, &myset)){// 这里处理鼠标memset(buf, 0, sizeof(buf));read(fd, buf, 50);printf("鼠标读出的内容是:[%s].\n", buf);}}return 0;
}

三、异步IO

1、何为异步IO?

(1)几乎可以认为,异步IO就是操作系统用软件实现的一套中断响应系统。类比硬件中断。

(2)异步IO的工作方法

  • 当前进程注册一个异步IO事件(使用signal注册一个信号SIGIO的处理函数),然后当前进程可以正常处理自己的事情;
  • 当异步事件发生后,当前进程会收到一个SIGIO信号,从而执行绑定的处理函数,来处理这个异步事件。

2、涉及的函数

(1)fcntl函数,主要设置异步通知。

  • 涉及的命令有F_GETFL(获取flag)、F_SETFL、O_ASYNC(表明可以接收异步通知)、F_SETOWN(设置通知谁(一般都是通知当前进程));

(2)signal或sigaction函数(SIGIO)

3、代码实践

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>int mousefd = -1;// 绑定到SIGIO信号,在函数内处理异步通知事件
void func(int sig)
{char buf[200] = {0};if (sig != SIGIO)return;read(mousefd, buf, 50);printf("鼠标读出的内容是:[%s].\n", buf);
}int main(void)
{// 读取鼠标char buf[200];int flag = -1;mousefd = open("/dev/input/mouse1", O_RDONLY);if (mousefd < 0){perror("open:");return -1;} // 把鼠标的文件描述符设置为可以接受异步IOflag = fcntl(mousefd, F_GETFL);flag |= O_ASYNC;fcntl(mousefd, F_SETFL, flag);// 把异步IO事件的接收进程设置为当前进程fcntl(mousefd, F_SETOWN, getpid());// 注册当前进程的SIGIO信号捕获函数signal(SIGIO, func);// 读键盘,在这里是当前进程while (1){memset(buf, 0, sizeof(buf));read(0, buf, 5);printf("键盘读出的内容是:[%s].\n", buf);}return 0;
}

四、存储映射IO

1、反映在mmap函数

  • 把一个文件和一段内存映射起来。比如LCD设备文件和显存的对应。

2、例子

  • LCD显示,IPC之共享内存

3、存储映射IO的特点

(1)共享而不是复制,减少内存操作。

(2)处理大文件时效率高(一般用于视频处理),小文件不划算。

高级IO(文件的读写)——并发式IO的解决方案(解决多路阻塞式IO的方案)相关推荐

  1. 高级IO(文件的读写)——阻塞式IO的困境、非阻塞式IO

    以下内容源于朱有鹏<物联网大讲堂>课程的学习整理,如有侵权,请告知删除. 一.阻塞式IO的困境 1.程序中读取键盘 int main(void) {// 读取键盘// 键盘就是标准输入,s ...

  2. AIO,BIO,NIO:同步阻塞式IO,同步非阻塞IO,异步非阻塞IO

    BIO,同步阻塞式IO,简单理解:一个连接一个线程 NIO,同步非阻塞IO,简单理解:一个请求一个线程 AIO,异步非阻塞IO,简单理解:一个有效请求一个线程 IO:阻塞IO BIO:同步阻塞IO.服 ...

  3. 从阻塞式IO到epoll——IO精讲

    Linux虚拟文件系统的理解 VFS 是一棵树, 树上的节点可以映射到对应的物理位置 与之对应的,什么是实际上的文件系统呢,比如说Windows操作系统上的,D盘对应的就是那块磁盘,C盘对应的就是这块 ...

  4. 阻塞式IO和非阻塞式IO

    什么是阻塞式IO,什么是非阻塞式IO?区分他们有何用? 阻塞式IO:IO即input/output,阻塞式IO指的是"一旦输入/输出工作没有完成,则程序阻塞,直到输入/输出工作完成" ...

  5. 五种网络IO模型:阻塞式IO 非阻塞式IO IO复用(IO multiplexing) 信号驱动式IO 异步IO

    文章目录 五种网络IO模型 举例说明 阻塞式I/O模型 非阻塞式I/O I/O多路复用 信号驱动式I/O 异步I/O 比较结果 总结 同步 异步 阻塞 非阻塞 阻塞/非阻塞: 同步/异步: 举例子:小 ...

  6. Servlet3.1 新增的非阻塞式IO

    Servlet3.1新增的新特性 强制更改sessionId 由HttpServletRequest 的changeSessionId()方法实现 非阻塞式IO 非阻塞式IO 我们应该知道Servle ...

  7. 服务端thrift 使用非阻塞式IO报异常Got an IOException in internalRead!

    参考:https://blog.csdn.net/z13192905903/article/details/103181204 参考:https://blog.csdn.net/xmtblog/art ...

  8. Python之IO模式 阻塞式io 非阻塞io 多路复用io 异步io 信号驱动io

    参考:https://www.cnblogs.com/alex3714/articles/5248247.html 提高:http://www.cnblogs.com/alex3714/article ...

  9. Java.IO 字符流读写文件

    点击上方 IT牧场 ,选择 置顶或者星标 技术干货每日送达! 一.序 上一篇我们谈了 java.IO 文件字节流读写操作(能懂系列Java.io文件字节流读写)大家应该都很熟悉了.但是中文和英文在字符 ...

最新文章

  1. .NET Core也可以使用MongoDB了
  2. 如何从几何角度上理解方程组只有一个解_深度科普---电磁波(三):无激励下的真空中的Maxwell方程组的解...
  3. 在NPP运行Python报错:SyntaxError: Non-ASCII character '\xe5' in file的解决方法
  4. python编程(python和c相互调用)
  5. 练打字-测试看图说话(AD安装)
  6. html二维坐标系转换,旋转坐标系 转换工具
  7. STORM的三种事务
  8. java 不同时区时间转换_Java中的时区转换小结
  9. Fireworks-CS5入门到高级129讲视频教程
  10. 聚类分析 距离 matlab,matlab聚类分析_matlab
  11. 修改了DNS服务器网速慢,网络速度缓慢怎么办?轻松一键修改DNS设置让网速提升五倍...
  12. 论文阅读 (54):DeepFool: A Simple and Accurate Method to Fool Deep Neural Networks
  13. 沧海桑田:Linux 系统启动的演进模型与发展变化
  14. 《人生的智慧》-叔本华著[韦启昌-(译)]
  15. illumina 二代测序原理及过程
  16. 便利贴--25{uniapp移动端滑动模块-因为uniapp打包后没有window,所以要另外去做监听和触控事件的传递}
  17. 如何阅读数据手册datasheet
  18. 不要被假相迷惑-有意思的声卡驱动
  19. 这所年轻大学,被誉为中国离科学最近的大学!
  20. 结构体练习——青蛙吃蚊子

热门文章

  1. 前端框架开始学习Vue(一)
  2. 【LA3415 训练指南】保守的老师 【二分图最大独立集,最小割】
  3. Git的GUI工具sourcetree的使用
  4. javascript 反斜杠\
  5. [转]基于图的机器学习技术:谷歌众多产品和服务背后的智能
  6. imgareaselect 缩略图 裁剪图片
  7. [18]Debian Linux Install GNU GCC Compiler and Development Environment
  8. [译] 论 Rust 和 WebAssembly 对源码地址索引的极限优化
  9. 学习API HOOK,编写了一个winsock 的封包抓取程序,可免费使用;
  10. Oracle 存储过程错误之PLS-00201: 必须声明标识符