020303阶段三 I/O复用 select和epoll的文件描述符管理
目录
- 一、学习的知识点
- 1 五种 I/O
- 1.1 阻塞式I/O
- 1.2 非阻塞式I/O
- 1.3 I/O复用(select 和pool)
- 1.3.1 select 文件描述符的管理
- select 缺点
- epoll
- 1.4 信号驱动I/O
- 1.5 异步I/O
- 二、上课没有听懂或者没有理解的地方
- 三、当天学习的收获
一、学习的知识点
man 2 属于系统调用
read 系统调用 先到内核空间(操作系统层)取数据 ,存放到 buff(应用层 用户空间)
1 五种 I/O
1.1 阻塞式I/O
通过read系统调用 到内核空间读取数据到用户空间,没有数据读取时 会阻塞。占用资源
1.2 非阻塞式I/O
阻塞和非阻塞是针对文件描述符来说。
通过 fcntl 函数设置 文件描述符的属性 默认为阻塞 可以设置为非阻塞 fd ctrl
1.3 I/O复用(select 和pool)
对I/O的操作只有 读 写,
1.3.1 select 文件描述符的管理
select 相当于一个管家 管理和socket有关的所有文件描述符 select只用一个进程就可以实现群聊服务器
select要知道当前进程的最大文件描述符是多少
管什么:暂时只管理 文件描述符的可读事件 可读事件(新的客户端连接、 文件描述符有数据可读包括客户端下线)
管理?文件描述符
会知道新客户端连按時文件描述符
会知道有数据需要去取的文件描述符
会知道下线的文件描述符
函数等待集合中产生可读事件的文件描述符。连接一个客户端 集合的值会变,哪个文件描述符产生可读事件 集合就变成几。 fd_ set是一个输入输出参数
- int select(int nfds, fd_ set *readfds, fd_ set *writefds,fd set *exceptfds, struct timeval *t imeout) ;
- 参数1:当前进程 最大文件描述符的数值是多少
- 参数2:文件描述符的可读事件集合
- 参数3 可写
- 参数4 异常
- 返回值:有几个文件描述符产生事件 就返回几
select 缺点
通过轮询查找文件描述符 如果文件描述符太多 效率就不高 没有可读事件产生会等待 select阻塞
对文件描述符的集合操作
- void FD_ CLR(int fd, fd_ set *set); 从集合删除某个文件描述符
- int FD_ ISSET(int fd, fd_ set *set); 判断集合中是否包含某个文件描述符
- void FD SET(int fd, fd_ set *set); 吧文件描述符加入集合
- void FD_ ZERO(fd_ set *set); 把集合清空
int maxfd = listen_fd;fd_set rset; //文件描述符集合fd_set allset; //放最新最全的文件描述符FD_ZERO(&allset);FD_ZERO(&rset);FD_SET(listen_fd, &allset);//吧 listen_fd放入allset 里面 交给select 监管cout << "select is wait..." << endl;char buff[1024] = { 0 };while (1){rset = allset; //因为select每返回一次 rset存放的都是产生事件的文件描述符的集合 其他的文件描述符被丢弃 //所以每返回一次 都要把最全的集合给他//参数1 fd数量 比如最大文件描述符为6 则轮询0-6 7个文件描述符 一旦select返回 rset会变成已经产生可读事件的文件描述符的集合 //如果两个文件描述符产生事件 就变成两个对应的文件描述符的集合int n = select(maxfd + 1, &rset, NULL, NULL, NULL); //n个文件描述符产生事件//select返回有两种情况:1 有新客户端连接 2 文件描述符有数据可读//情况1 如果select返回后 rset存放的是listen_fd 说明是监听套接字产生了可读事件 意味着有新的客户端的连接cout << "select is return .." << n << endl;//有可能是新的客户端连接上来 rset里面的文件描述符是不是socket_fdif (FD_ISSET(listen_fd, &rset)) //判断 listen_fd是否在集合里面{//证明有新的客户端连接进来//4. 如果没有客户端完成三次握手,程序会阻塞在accept cout << "wait" << endl;//此时的accept不阻塞 直接连接int con_fd = accept(listen_fd, (struct sockaddr*)&cli_add, &add_len);if (con_fd == -1)ERR_EXT("accept");printf("\r\n con_fd: %d client connected %s:%d \r\n", con_fd, inet_ntoa(cli_add.sin_addr), ntohs(cli_add.sin_port));//con_fd 表示新的客户端 这个客户端立马加入select 管理FD_SET(con_fd, &allset);//把新的客户端文件描述符放入容器allfd.push_back(con_fd);if (con_fd > maxfd)maxfd = con_fd;}else //否则是收到消息 rest变成产生可读事件对应的文件描述符 此时要 read 取出数据 否则会一直触发select{//read取走数据 到底是哪个for (it = allfd.begin(); it != allfd.end(); it++){if (FD_ISSET(*it, &rset)){int fd = *it;int ret = read(fd, buff, 1024);if (ret == 0){cout << "client is off fd=" << *it << endl;//把这个客户端从集合删除FD_CLR(fd, &allset);allfd.erase(it);break;}if (ret > 0){cout << "read:" << buff << endl;write(fd, buff, 1024);bzero(buff, 1024);break;}}}cout << "new message.." << endl;}}
epoll
与select相比,优点是 不需要遍历fd 直接读取到产生事件的fd
- 函数原型:int epoll_create(int size)
- 功能:创建一个epoll句柄 管理器 统一管理文件描述符
- 参数:
- 返回值:成功返回文件描述符 失败返回 -1
- 函数原型:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
- 功能:将fd以 op(增加 修改 删除) 的方式 给 epfd 管理
- 参数:
- 返回值:成功返回文件描述符 失败返回 -1
struct epoll_event eventarry[5];int epo = epoll_create(10);//创建一个EPOLL句柄 创建一个管理器struct epoll_event event;event.events = EPOLLIN;//表示 关心他的可读事件event.data.fd = listen_fd; //data结构体 char buff[1024] = { 0 };//表示把listen_fd添加到epo管理 event为listen_fd的属性 包含管理的方式 关心listen_fd的可读事件 并且带一个数据:这个数据放fd epoll_ctl(epo, EPOLL_CTL_ADD, listen_fd, &event);while (1){//int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);epoll_wait(epo, eventarry, 5, -1); //会阻塞 参数2 存放事件的数组 放epoll返回后产生事件的结构体 参数3 不能大于 epoll_create 的参数 参数4 超时 不关心//假如 一个文件描述符产生事件 相应的属性结构体 就会放入 参数2 的数组中 if (eventarry[0].data.fd == listen_fd){//有新的客户端连接int con_fd = accept(listen_fd, (struct sockaddr*)&cli_add, &add_len);struct epoll_event new_event;new_event.events = EPOLLIN;//表示 关心他的可读事件new_event.data.fd = con_fd; //data结构体 epoll_ctl(epo, EPOLL_CTL_ADD, con_fd, &new_event); //把 con_fd加入 epoll 管理}else{int fd = eventarry[0].data.fd;read(fd, buff, 1024);cout << "read:" << buff << endl;}}
1.4 信号驱动I/O
1.5 异步I/O
二、上课没有听懂或者没有理解的地方
三、当天学习的收获
020303阶段三 I/O复用 select和epoll的文件描述符管理相关推荐
- select、poll、epoll的文件描述符上限问题
select.poll.epoll是三个常用的I/O复用,之前使用过程中一直没很深入思考,只知道①select有文件描述符上限 ②poll是select的改进,去掉了文件描述符上限 ③epoll是前两 ...
- 【C/C++服务器开发】文件,文件描述符,I/O多路复用,select / poll / epoll 详解
文章目录 一.前言 1.文件的概念 2.文件描述符和文件指针 文件描述符 文件描述符和文件指针的区别 文件描述符太多了怎么办 二.I/O多路复用 1.I/O多路复用的由来 不要打电话给我,有需要我会打 ...
- select中文件描述符上限为什么是1024?
一.两个1024 select中存放文件描述符的数组大小FD_SETSIZE为1024 进程的文件描述符上限默认是1024,正是因为这个原因,select设计时才把数组大小设计为1024 二.问题来了 ...
- Select()系统调用及文件描述符集fd_set的应用
在网络程序中,一个进程同时处理多个文件描述符是很常见的情况.select()系统调用可以使进程检测同时等待的多个I/O设备,当没有设备准备好时,select()阻塞,其中任一设备准备好时,select ...
- linux内核中的文件描述符(三)--fd的回收
linux内核中的文件描述符(三)--fd的回收 Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blog.csd ...
- io多路复用的原理和实现_IO多路复用的三种机制:select 、poll 、epoll
目录 概述 IO多路复用本质 IO多路复用的优势 IO多路复用Select机制 IO多路复用Poll机制 IO多路复用Epoll机制 select,poll,epoll机制区别总结 php7进阶到架构 ...
- Linux select/poll/epoll
参考地址:https://www.jianshu.com/p/fe54ca4affe8 本文讨论的背景是Linux环境下的network IO. 一. 概念说明 在进行解释之前,首先要说明几个概念: ...
- IO多路复用及select poll epoll讲解
https://blog.csdn.net/weixin_43367828/article/details/84676775 https://www.jianshu.com/p/6a684546477 ...
- select poll epoll
一 虚拟存储器 一个作业在运行之前,没有必要把全部作业装入内存,而仅将那些当前要运行的 那部分页面或段,先装入内存便可以启动运行,其余部分暂时驻留磁盘 程序在运行时,如果他所要访问的页面或者端已调入内 ...
最新文章
- list保留小数位数
- gulp.js 的安装以及使用
- python3精要(32)-生成器表达式
- linux inotifywait脚本,使用inotify/fswatch构建自动监控脚本
- arch linux 入门,arch linux 从来就不是给新手入门用的
- Spark初识-弹性分布式数据集RDD
- python变量和对象的关系_Python变量与对象引用的区别
- javascript正则表达式一
- SQL:两种获取时间类型日期部分的方法
- SAE J1939协议(二)
- java基本数据从低到高_java基本数据类型之间的转换
- socket里sendto()函数
- 完整版第四方Oreo易支付源码+28K易支付源码
- 自动点击android按钮,Android实现自动点击无障碍服务功能的实例代码
- 真香啊,Python 轻松制作制作GIF动图
- MySQL-14使用子查询-必知必会
- DZone每日必读-News:2022 年 Java 开发:预测和选定趋势
- 【回溯法】机器零件加工-最优加工顺序
- Makefile 书写
- Android验证码倒计时实现方式总结