1.为什么有阻塞IO
(1)常见的阻塞:wait、pause、sleep等函数,read和write某些特殊文件时
(2)阻塞式的好处,在阻塞等待的进程不消耗CPU运行,提高性能。

2.如何实现非阻塞IO访问
(1)O_NONBLOCK和fcntl

3.阻塞式IO的困境
(1)程序中读取键盘

#include <stdio.h>
#include <string.h>
#include <unistd.h>int main(void)
{char buf[100];memset(buf,0,sizeof(buf));printf("before read\n");//读取键盘键盘就是标准输入,stdinread(0,buf,2);//read默认是阻塞的printf("读出的内容是:[%s]\n",buf);return 0;
}

(2)程序中读取鼠标
这里的鼠标输入在/dev/input/mouse1有的是在mouse0下面通过cat /dev/input/mouse0或者mouse1然后移动鼠标出现乱码则就是鼠标输入设备。

#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main(void)
{int fd = -1;char buf[200];fd = open("/dev/input/mouse0",O_RDONLY);if(fd < 0){perror("open");return -1;}memset(buf,0,sizeof(buf));printf("before read\n");//读取鼠标read(fd,buf,5);//read默认是阻塞的printf("读出的内容是:[%s]\n",buf);return 0;
}

(3)程序中同时读取键盘鼠标

#include <sys/stat.h>
#include <fcntl.h>int main(void)
{int fd = -1;char buf[200];fd = open("/dev/input/mouse0",O_RDONLY);//打开鼠标if(fd < 0){perror("open");return -1;}memset(buf,0,sizeof(buf));printf("before 鼠标 read\n");//读取鼠标read(fd,buf,5);//read默认是阻塞的printf("鼠标读出的内容是:[%s]\n",buf);memset(buf,0,sizeof(buf));printf("before 键盘 read\n");//读取键盘键盘就是标准输入,stdinread(0,buf,2);//read默认是阻塞的printf("键盘读出的内容是:[%s]\n",buf);return 0;
}

(4)问题分析
像这种情况就只能先读鼠标再读键盘这就是阻塞式的缺陷

4.并发式IO
(1)非阻塞式IO

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

5.多路复用IO
(1)何为IO多路复用(IO multiplexing)
(2)用在什么地方:多路非阻塞式IO
(3)select和poll(本身是阻塞式函数)

int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
参数1:文件描述符的个数(文件IO中最大文件描述符+1)
参数2:要读的文件描述符的集合(相当于结构体,放多个需要读的文件描述符)
参数3:要写的多个文件描述符
参数4:看文件描述符是否出错
参数5:设置超时时间(如果这段事间一直没有IO事件发生就返回0)
返回值:返回发生了几次IO事件
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
参数1:多个文件描述符的集合
参数2:放入这个集合的文件描述符个数+1
参数3:超时时间
返回值:返回发生了几次IO事件

select函数实现

#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>int main(void)
{int fd = -1;int ret = -1;fd_set myset;char buf[200];struct timeval tm;fd = open("/dev/input/mouse0",O_RDONLY);//打开鼠标if(fd < 0){perror("open");return -1;}//当前有两个fd,1个是fd,1个是0//处理mysetFD_ZERO(&myset);//先清零FD_SET(fd,&myset);//设置fdFD_SET(0,&myset);//设置0这个fdtm.tv_sec = 10;//设置秒tm.tv_usec = 0;//设置微妙(两个秒数是相加的)//int select(int nfds, fd_set *readfds, fd_set *writefds,//fd_set *exceptfds, struct timeval *timeout);ret = select(fd+1,&myset,NULL,NULL,&tm);if(ret < 0){perror("select");return -1;}else if(ret == 0){printf("超时了\n");}else{//等到了一路IO,然后去监测是哪个IO到了if(FD_ISSET(0,&myset)){//这里处理键盘memset(buf,0,sizeof(buf));//读取键盘键盘就是标准输入,stdinread(0,buf,5);//read默认是阻塞的printf("键盘读出的内容是:[%s]\n",buf);}else if(FD_ISSET(fd,&myset)){//这里处理鼠标memset(buf,0,sizeof(buf));read(fd,buf,5);//read默认是阻塞的printf("鼠标读出的内容是:[%s]\n",buf);}}return 0;
}

poll函数实现:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <poll.h>int main(void)
{int fd = -1;int ret = -1;struct pollfd myfds[2] = {0};char buf[200];struct timespec tm;fd = open("/dev/input/mouse0",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;//等待读操作tm.tv_sec = 10000;//int poll(struct pollfd *fds, nfds_t nfds, int timeout);//ret = poll(myfds,2,tm.tv_sec);//2个文件描述符,10000毫秒ret = poll(myfds,fd,10000);//2个文件描述符,10000毫秒,这里写fd文件运行>直接退出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));//读取键盘键盘就是标准输入,stdinread(0,buf,5);//read默认是阻塞的printf("键盘读出的内容是:[%s]\n\r",buf);}if(myfds[1].events == myfds[1].revents){//这里处理鼠标memset(buf,0,sizeof(buf));read(fd,buf,50);//read默认是阻塞的printf("鼠标读出的内容是:[%s]\n",buf);}}return 0;
}

(4)外部阻塞式,内部非阻塞式自动轮询多路阻塞式IO

6.异步通知(异步IO)
(1)异步IO就是操作系统用软件实现的一套中断系统。
(2)异步IO的工作方法:我们当前进程注册一个异步IO事件(使用signal注册一个信号SIGIO的处理函数),然后当前进程可以正常处理自己的事情,当异步事件发生后当前进程会收到一个SIGIO信号从而执行绑定的处理函数去处理这个异步事件。
(3)涉及函数(fcntl(F_GETFL、F_SETFL、O_ASYNC、F_SETOWN))、signal或sigaction(SIGIO)
(4)代码实现

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int mousefd = -1;//异步通知函数,绑定SIGIO信号,在函数内处理异步通知事件
void func(int sig)
{char buf[200] = {0};if(sig != SIGIO)return;//读取鼠标read(mousefd,buf,5);//read默认是阻塞的printf("鼠标读出的内容是:[%s]\n",buf);}int main(void)
{char buf[200];int flag = -1;mousefd = open("/dev/input/mouse0",O_RDONLY);//打开鼠标if(mousefd < 0){perror("open");return -1;}//注册异步通知(把鼠标的文件描述符设置为可以接受异步IO)flag = 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));//读取键盘键盘就是标准输入,stdinread(0,buf,5);//read默认是阻塞的printf("键盘读出的内容是:[%s]\n",buf);}return 0;
}

7.存储映射IO
(1)mmap函数
(2)LCD显示和IPC之共享内存
(3)存储映射的特点:共享而不是复制,减少内存操作。处理大文件时效率高,小文件不划算

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

linux非阻塞IO与阻塞IO的应用相关推荐

  1. Linux网络编程 | IO模型 :阻塞IO、非阻塞IO、信号驱动IO、异步IO、多路复用IO

    目录 IO模型 阻塞与非阻塞 同步与异步 阻塞IO 非阻塞IO 信号驱动IO 多路复用IO 异步IO IO模型 根据各自的特性不同,IO模型被分为阻塞IO.非阻塞IO.信号驱动IO.异步IO.多路复用 ...

  2. python复制文件夹不阻塞_Python学习第54天(阻塞(blocking) IO和非阻塞(non-blocking)IO)...

    今天之所以这么早结束,主要是因为自己脑子不够用了,发现最近的定义有点多,完全搞不清楚了,打算早点睡觉,今天的内容估计要引用很多别人的部分了. 看到题目的四个东东是不是惊呆了,我也是惊呆了,同时脑子还跟 ...

  3. 【多线程】0.理解一下5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO

    5种IO模型.阻塞IO和非阻塞IO.同步IO和异步IO 看了一些文章,发现有很多不同的理解,可能是因为大家入切的角度.环境不一样.所以,我们先说明基本的IO操作及环境. 本文是在<UNIX网络编 ...

  4. java epoll select_Java 非阻塞 IO 和异步 IO

    点击上方 Java后端,选择 设为星标 优质文章,及时送达 作者 | HongJie 链接 | javadoop.com/post/nio-and-aio 本文将介绍非阻塞 IO 和异步 IO,也就是 ...

  5. linux select read阻塞_linux下的IO模型详解

    开门见山,Linux下的如中IO模型:阻塞IO模型,非阻塞IO模型,IO复用模型,信号驱动IO模型,异步IO模型,见下图 接下来一一讲解这5种模型 阻塞型IO:最简单的一种IO模型,简单理解就是死等, ...

  6. 5种网络IO模型:阻塞IO、非阻塞IO、异步IO、多路复用IO、信号驱动IO

    目录 前言 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) 模型间的区别 ...

  7. 同步IO、异步IO、阻塞IO、非阻塞IO、复用IO

    参考:同步IO 异步IO 作者:今天天气眞好 发布时间: 2021-04-19 09:42:29 网址:https://blog.csdn.net/qq_51118175/article/detail ...

  8. Java 非阻塞 IO 和异步 IO

    转载自 Java 非阻塞 IO 和异步 IO 上一篇文章介绍了 Java NIO 中 Buffer.Channel 和 Selector 的基本操作,主要是一些接口操作,比较简单. 本文将介绍非阻塞 ...

  9. 高级IO--1 ---(五种典型IO,阻塞IO,非阻塞IO,信号驱动IO,异步IO, IO多路转接)

    高级IO: 五种典型IO: 阻塞IO/非阻塞IO/信号驱动IO/异步IO/IO多路转接 IO多路转接模型:select/poll/epoll 五种典型IO 阻塞IO IO操作的流程:等待IO操作条件具 ...

最新文章

  1. “iloveyou88”比“ilovekale”好猜解的多
  2. Android面试题目之六---Handler,Looper和MessageQueue深入研究
  3. 代码评审的不可能三角
  4. c++ 8.整数加法实现
  5. linux命令行下载github文件,Linux命令行下使用GitHub
  6. 讲解Linux数据库安装
  7. 麻省理工学院(MIT)研究生学习指导—— 怎样做研究生
  8. Redis的RDB AOF DATABASE
  9. 数据库事务4种隔离级别及7种传播行为(三)
  10. julia: 如何序列化和反序列化?
  11. VCS带UPF的RTL低功耗仿真介绍
  12. filecoin lotus 转账fil流程和gas计算
  13. 网络安全学习笔记Day01—Day10
  14. 基于JAVA校内图书馆智能管理系统计算机毕业设计源码+数据库+lw文档+系统+部署
  15. VM虚拟机安装及应用
  16. 黄健翔,请你像个男人一样去向全国的球迷道歉!(摘自网络)
  17. ❥关于C++之函数指针函数对象
  18. 东北大学20级计算机C语言课设-航空订票系统
  19. Java,第一次作业——解一元二次方程
  20. 2015 史考特(Scottrade)开户指南 + 招商银行香港一卡通汇款【图文教程】

热门文章

  1. Java PBEParameterSpec 测试
  2. UNCTF2020的奇妙之旅-----CryptoMisc部分wp
  3. java 方法中final_Java中final的使用方法
  4. Java 8 特性 – 终极指南
  5. 优质的草原cc0高清摄影图片素材推荐,不容错过
  6. QT调用打印机的实现
  7. 简历通过率从40%直升100%,我是这样做的
  8. PYTHON爬取高德地图POI
  9. 海马323手动档省油技巧
  10. 论文学习:Occlusion Robust Face Recognition Based on Mask Learning