知识点: epoll模型(使用成员ptr携带信息), udp(#pragma pack结构体对齐), socketcan(帧过滤), Linux多路uart232tousb列表获取, 正则匹配, ASCII乱码检测, C++线程(lambda), 非阻塞读。
一、代码
#include
#include
#include
#include
#include
二、Unix下IO模型
UNIX5大IO模型:阻塞io、非阻塞io、io复用、信号驱动式io、异步io。
总的来说,IO操作分2阶段:
1)数据准备阶段;
2)内核空间复制回用户进程缓冲区阶段;
-前4种io:仍然属于同步io,只是由内核监听请求,收到请求后数据的拷贝过程还是要应用程序去等待执行,这段时间应用程序是阻塞的;
-异步io:你应用程序不用管了,你只需要告诉我(内核)你要做什么,我做完了直接把结果给你(数据从内核到用户态也不需要你干预);
-io模型——io复用(select、poll、epoll):
1)select:
int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
参数:监听的最大描述符+1、监听的读描述符集合rset、写描述符集合wset、异常描述符集合illset(传入传出参数),返回的请求数(对少个fd有动作),只能监听集合是否有动作,不能分清是什么动作、具体哪几个动作了,需要自己遍历描述符集合,如判断读描述符集合里的fd1是否动作了:FD_ISSET(fd1, &rset);
【缺点】:
1)有监听有上限数;
2)每次select函数调用都要将监听的描述符拷贝到内核;
3)内核中进行轮询一遍所有描述符变化;(在timeout时间之内不断轮询,fd对应的socketbuff是否有数据到达);
2)poll:相较于select的提升在于监听描述符上限优化了。
3)epoll:提升了select的1)无上限,2)只需要拷贝一次描述符集合到内核,对于3)==> 使用红黑树管理监听的fd,在查找、插入、删除速度快。内部维护一个就绪链表,某个fd就绪时,调用回调函数机制把就绪fd放入就绪链表中,调用epoll_wait只需要不断轮询就绪链表是否为空就ok,节省了CPU大量遍历的时间。
总结:
参考链接:IO多路复用——深入浅出理解select、poll、epoll的实现 - 知乎