当前位置: 首页 > news >正文

地方汽车网站模板购买外贸网站建设推广培训

地方汽车网站模板购买,外贸网站建设推广培训,百度网址大全免费下载,ppt模板哪里可以免费下载高级IO——五种IO模型 首先我们之前在基础IO部分就学过IO的过程分等待过程和读写过程#xff01; 比如我们的scanf除了从键盘缓冲区读取数据所花的时间#xff0c;主要的时间花费放在了等你输入的过程#xff01; 所以我们如果想提高我们的IO效率#xff0c;我们除了要缩…高级IO——五种IO模型 首先我们之前在基础IO部分就学过IO的过程分等待过程和读写过程 比如我们的scanf除了从键盘缓冲区读取数据所花的时间主要的时间花费放在了等你输入的过程 所以我们如果想提高我们的IO效率我们除了要缩减读取数据主要的是减少花费在等你输入的时间可是我们肯定不可能决定用户的输入速度所以我们就只能让这个等待时间我们的程序去做其他事情这样就可以减少等待IO花费的时间了 由此我们就可以引出我们的5种IO模型了我们用钓鱼做例子 阻塞IO: 在内核将数据准备好之前, 系统调用会一直等待. 所有的套接字, 默认都是阻塞方式 老老实实抓着一根杆子钓鱼鱼来了就拉钩否则就一直等 非阻塞IO: 如果内核还未将数据准备好, 系统调用仍然会直接返回, 并且返回EWOULDBLOCK错误码. 把杆放在池塘里面就走了过一段时间回来一次看一看有鱼就掉没鱼就离开去干其他事情。 信号驱动IO: 内核将数据准备好的时候, 使用SIGIO信号通知应用程序进行IO操作 放个信号器来鱼了信号器报警听到信号以后就去拉杆 IO多路转接: 实际上最核心在于IO多路转接能够同时等待多个文件 描述符的就绪状态. 一次性放很多鱼竿然后不停的检测所有鱼竿的情况那个鱼竿有鱼就去处理那一根鱼竿   异步IO: 由内核在数据拷贝完成时, 通知应用程序(而信号驱动是告诉应用程序何时可以开始拷贝数据). 直接让别人去钓鱼等别人调完鱼直接去取鱼 前面四种IO我们称之为同步IO我们先不看异步IO那种钓鱼的效率最高 当然是IO多路转接为什么因为杆多鱼竿多自然钓鱼就多因为不同鱼竿的等待时间重叠了本身就是提高效率 可是我们一般选择多是多路复用而不是异步IO。为什么呢因为首先异步IO看起来是让别人钓鱼但是在程序中我们就要创建线程或子进程去做事本身就要耗费较大资源而且一旦设计多线程就可能会出现很多问题大幅度提高程序的复杂性所以我们一般更青睐于多路转接的方法 接下来我们来学习系统专门为多路复用设计的接口 首先我们来介绍select 在此之前由于我们的fd都默认是阻塞式IO所以我们先要将想要的fd设置为非阻塞式IO。 这个时候我们就要先用fcntl去设置相应的fd呢 复制一个现有的描述符 cmdF_DUPFD . 获得 / 设置文件描述符标记 (cmdF_GETFD 或 F_SETFD). 获得 / 设置文件状态标记 (cmdF_GETFL 或 F_SETFL). 获得 / 设置异步 I/O 所有权 (cmdF_GETOWN 或 F_SETOWN). 获得 / 设置记录锁 (cmdF_GETLK,F_SETLK 或 F_SETLKW). 比如下面的程序就是先获取一个程序的旧的标志位然后我们再设置其为非阻塞 接下来我们就可以学习select呢 返回值n0的时候就代表有多少个fd已经就绪n0就是没有就绪但是倒计时已经到了n0就是出错了 timeval是一个结构体如下图分别是秒和微秒 并且timeval还是个输入输出形参数 也即比如我们设置的是5,0也即5秒返回一次如果过了两秒就有就绪了那么timeval这个时候就会使3,0. 然后我们再来了解最重要的是fd_set是什么 其实就是一张位图readfds里面响应的位置如果被设置为1则关心相应事件的读writefds则关心写 当传入的时候我们就是告诉内核那个fd我们要关心返回的时候传出的就是那个fd已经可以读取了不会产生等待了 我们在这里先讲一下select的一些限制既然fd_set是结构体那么其中等待的fd有没有上限呢是多少呢 不同的系统可能跑出来的是不一样的但是大差不差 并且我们每一次都要重新给select传表我们还要用一个辅助数组提前记录哪些fd我们要监听也是一个开销 所以我们可以总结一下select的优缺点 优点主要是已经实现了多路转接了 缺点 1.fd有上限 2.输入输出型参数多需要不停的数据拷贝和遍历修改会导致效率低下 3.而且还要辅助数组记录我们要关心的fd 下面是一个基于select的多路转接的单词翻译器的实现 然后我们在学习epoll之前先看一下poll 第一个参数就是一个struct pollfd的数组 第二个参数就是数组中元素的个数 第三个参数与select一致 至于struct pollfd的结构主要包含关心的fd,还有两个短整形变量 如果想要添加指令就只用将短整数上对应的宏就可以了 其中events是传入给poll的revents是poll要写入的我们进行读取就可以 poll相对于select首先克服了数量有限的问题并且减少了遍历并且不用我们维护辅助数组了 也更容易编写 但是我们仍然需要去不停遍历整个数组那么当数量增多以后主要矛盾就从等待变成了遍历了 如果学会了select那poll难度应该不大就不再过多赘述而epoll则在此基础之上又大幅度提高效率所以下面我们来学习epoll!!! epoll 的事件注册函数 . 它不同于 select() 是在监听事件时告诉内核要监听什么类型的事件 , 而是在这里先注册要监听的事件类型 . 第一个参数是 epoll_create() 的返回值 (epoll 的句柄 ). 第二个参数表示动作用三个宏来表示 . 第三个参数是需要监听的 fd. 第四个参数是告诉内核需要监听什么事 . 第二个参数的取值 : EPOLL_CTL_ADD 注册新的 fd 到 epfd 中 EPOLL_CTL_MOD 修改已经注册的 fd 的监听事件 EPOLL_CTL_DEL 从 epfd 中删除一个 fd struct epoll_event 结构如下 events 可以是以下几个宏的集合 EPOLLIN : 表示对应的文件描述符可以读 ( 包括对端 SOCKET 正常关闭 ); EPOLLOUT : 表示对应的文件描述符可以写 ; EPOLLPRI : 表示对应的文件描述符有紧急的数据可读 ( 这里应该表示有带外数据到来 ); EPOLLERR : 表示对应的文件描述符发生错误 ; EPOLLHUP : 表示对应的文件描述符被挂断 ; EPOLLET : 将 EPOLL 设为边缘触发 (Edge Triggered) 模式 , 这是相对于水平触发 (Level Triggered) 来说的 . EPOLLONESHOT只监听一次事件 , 当监听完这次事件之后 , 如果还需要继续监听这个 socket 的话 , 需要 再次把这个socket 加入到 EPOLL 队列里 收集在 epoll 监控的事件中已经发送的事件 . 参数 events 是分配好的 epoll_event 结构体数组 . epoll 将会把发生的事件赋值到 events 数组中 (events 不可以是空指针内核只负责把数据复制到这个 events数组中不会去帮助我们在用户态中分配内存 ). maxevents 告之内核这个 events 有多大这个 maxevents 的值不能大于创建 epoll_create() 时的 size. 参数 timeout 是超时时间 ( 毫秒 0 会立即返回 -1 是永久阻塞 ). 如果函数调用成功返回对应 I/O 上已准备好的文件描述符数目如返回 0 表示已超时 , 返回小于 0 表示函 数失败 学了epoll的基本使用以后我们来学习一下epoll的原理 当某一进程调用 epoll_create 方法时 Linux 内核会创建一个 eventpoll 结构体这个结构体中有两个成 员与epoll 的使用方式密切相关 . 主要是一个红黑树和一个双链表的队列 每个被检测的fd都会被放入红黑树一旦事件就绪就会调用回调函数让操作系统从红黑树中找到相关的rbn成员然后读取其信息然后在等待队列中添加这样就我们进行读取事件的时候就是在等待队列中读取事件了并且在这个过程中事件主动回调时间复杂度为o(1)比我们之前的select和poll效率拥有了质的提升 总结一下 , epoll 的使用过程就是三部曲 : 调用 epoll_create 创建一个 epoll 句柄 ; 调用 epoll_ctl, 将要监控的文件描述符进行注册 ; 调用 epoll_wait, 等待文件描述符就绪 ; epoll 的优点 ( 和 select 的缺点对应 ) 接口使用方便 : 虽然拆分成了三个函数 , 但是反而使用起来更方便高效 . 不需要每次循环都设置关注的文 件描述符, 也做到了输入输出参数分离开 数据拷贝轻量 : 只在合适的时候调用 EPOLL_CTL_ADD 将文件描述符结构拷贝到内核中 , 这个操作并不频 繁( 而 select/poll 都是每次循环都要进行拷贝 ) 事件回调机制 : 避免使用遍历 , 而是使用回调函数的方式 , 将就绪的文件描述符结构加入到就绪队列中 , epoll_wait 返回直接访问就绪队列就知道哪些文件描述符就绪 . 这个操作时间复杂度 O(1). 即使文件描述 符数目很多, 效率也不会受到影响 . 没有数量限制: 文件描述符数目无上限 我们再来讲一下epoll的工作模式 epoll有2种工作方式-水平触发(LT)和边缘触发(ET) 假如有这样一个例子 : 我们已经把一个 tcp socket 添加到 epoll 描述符 这个时候 socket 的另一端被写入了 2KB 的数据 调用 epoll_wait 并且它会返回 . 说明它已经准备好读取操作 然后调用 read, 只读取了 1KB 的数据 继续调用 epoll_wait...... 水平触发 Level Triggered 工作模式 epoll 默认状态下就是 LT 工作模式 . 当 epoll 检测到 socket 上事件就绪的时候 , 可以不立刻进行处理 . 或者只处理一部分 . 如上面的例子 , 由于只读了 1K 数据 , 缓冲区中还剩 1K 数据 , 在第二次调用 epoll_wait 时 , epoll_wait 仍然会立刻返回并通知 socket 读事件就绪 . 直到缓冲区上所有的数据都被处理完 , epoll_wait 才不会立刻返回 . 支持阻塞读写和非阻塞读写 边缘触发 Edge Triggered 工作模式 如果我们在第 1 步将 socket 添加到 epoll 描述符的时候使用了 EPOLLET 标志 , epoll 进入 ET 工作模式 . 当 epoll 检测到 socket 上事件就绪时 , 必须立刻处理 . 如上面的例子 , 虽然只读了 1K 的数据 , 缓冲区还剩 1K 的数据 , 在第二次调用 epoll_wait 的时候 , epoll_wait 不会再返回了 . 也就是说 , ET 模式下 , 文件描述符上的事件就绪后 , 只有一次处理机会 . ET 的性能比 LT 性能更高 ( epoll_wait 返回的次数少了很多 ). Nginx 默认采用 ET 模式使用 epoll. 只支持非阻塞的读写 select 和 poll 其实也是工作在 LT 模式下 . epoll 既可以支持 LT, 也可以支持 ET. 对比 LT 和 ET LT 是 epoll 的默认行为 . 使用 ET 能够减少 epoll 触发的次数 . 但是代价就是强逼着程序猿一次响应就绪过程中就把 所有的数据都处理完. 相当于一个文件描述符就绪之后 , 不会反复被提示就绪 , 看起来就比 LT 更高效一些 . 但是在 LT 情况下如果也能做到 每次就绪的文件描述符都立刻处理, 不让这个就绪被重复提示的话 , 其实性能也是一样的 . 另一方面 , ET 的代码复杂程度更高了 . 理解 ET 模式和非阻塞文件描述符 使用 ET 模式的 epoll, 需要将文件描述设置为非阻塞 . 这个不是接口上的要求 , 而是 工程实践 上的要求 . 假设这样的场景 : 服务器接受到一个 10k 的请求 , 会向客户端返回一个应答数据 . 如果客户端收不到应答 , 不会发送第 二个10k 请求 . 如果服务端写的代码是阻塞式的read, 并且一次只 read 1k 数据的话 (read 不能保证一次就把所有的数据都读出来 , 参考 man 手册的说明 , 可能被信号打断 ), 剩下的 9k 数据就会待在缓冲区中 此时由于 epoll 是 ET 模式 , 并不会认为文件描述符读就绪 . epoll_wait 就不会再次返回 . 剩下的 9k 数据会一直在缓 冲区中. 直到下一次客户端再给服务器写数据 . epoll_wait 才能返回 但是问题来了. 服务器只读到 1k 个数据 , 要 10k 读完才会给客户端返回响应数据 . 客户端要读到服务器的响应 , 才会发送下一个请求 客户端发送了下一个请求, epoll_wait 才会返回 , 才能去读缓冲区中剩余的数据 所以 , 为了解决上述问题 ( 阻塞 read 不一定能一下把完整的请求读完 ), 于是就可以使用非阻塞轮训的方式来读缓冲区 , 保证一定能把完整的请求都读出来. 而如果是 LT 没这个问题 . 只要缓冲区中的数据没读完 , 就能够让 epoll_wait 返回文件描述符读就绪 . 也即如果设置为非阻塞的时候我们反复读取一旦读完就会出错返回如果阻塞模式我们就会阻塞在读的地方这显然是我们不能接受的所以我们要把读设为非阻塞模式 epoll 的使用场景 epoll 的高性能 , 是有一定的特定场景的 . 如果场景选择的不适宜 , epoll 的性能可能适得其反 . 对于多连接 , 且多连接中只有一部分连接比较活跃时 , 比较适合使用 epoll. 例如 , 典型的一个需要处理上万个客户端的服务器 , 例如各种互联网 APP 的入口服务器 , 这样的服务器就很适合 epoll. 如果只是系统内部 , 服务器和服务器之间进行通信 , 只有少数的几个连接 , 这种情况下用 epoll 就并不合适 . 具体要根 据需求和场景特点来决定使用哪种IO模型 1.epoll惊群效应产生的原因 在Linux下使用epoll编写过socket的服务端程序在多线程环境下可能会遇到epoll的惊群效应。那么什么是惊群效应呢。其产生的原因是什么呢 在多线程或者多进程环境下有些人为了提高程序的稳定性往往会让多个线程或者多个进程同时在epoll_wait监听的socket描述符。当一个新的链接请求进来时操作系统不知道选派那个线程或者进程处理此事件则干脆将其中几个线程或者进程给唤醒而实际上只有其中一个进程或者线程能够成功处理accept事件其他线程都将失败且errno错误码为EAGAIN。这种现象称为惊群效应结果是肯定的惊群效应肯定会带来资源的消耗和性能的影响。 那么如何解决这个问题。 2.惊群问题的解决方法 多线程环境下解决惊群解决方法 这种情况不建议让多个线程同时在epoll_wait监听的socket而是让其中一个线程epoll_wait监听的socket,当有新的链接请求进来之后由epoll_wait的线程调用accept建立新的连接然后交给其他工作线程处理后续的数据读写请求这样就可以避免了由于多线程环境下的epoll_wait惊群效应问题。 最后再把基于epoll的多路转接翻译服务器的代码贴在这里这篇文章就到底为止了 感谢观看
http://www.w-s-a.com/news/126513/

相关文章:

  • 国家建设执业资格注册中心网站企业手机网站建设机构
  • 内容管理系统做网站怎么做英文版的网站
  • 浙江省专业网站制作网站建设网站设计及内容策划
  • 浙江门户网站建设公司做网站上哪买空间
  • 郑州网站怎么推广贵阳市网站建设
  • 规范网站建设福州外贸网站建设推广
  • 平台电商网站开发传媒公司排行
  • 在哪给人做网站怎么样制作一个网页
  • 网站更改文章标题广西新闻
  • 专业做网站路桥寺院网站建设方案
  • 网站维护与优化教程广州做网站的网络公司排名
  • 网站做贷款许可证网站改版方案模板
  • 装饰公司怎么做网站嘉兴网站制作推广
  • 深圳兼职做网站涿州网站制作
  • 能找本地人做导游的网站app模板素材下载免费
  • 网站积分的作用网站开发需要看相关书籍
  • 建设银行总行网站alexa排名与什么有关系
  • 阿里云服务器发布网站收款网站怎么建设
  • 开发东莞网站制作公司做网站优化步骤
  • 网站版权信息的正确写法如何制作网络游戏
  • 郑州移动端网站建设如何在网上推广自己的公司
  • 企业建站源码系统破解网站后台
  • 石家庄网站开发报价企业注册资本代表什么
  • 招商平台公司宁波seo教程推广平台
  • 哪些网站可以做房产推广垂直门户网站都有什么
  • 不得不知道的网站金石项目管理软件
  • 怎么恢复网站数据库网站开发作业代做
  • 哪里建设网站最好用中国第五冶金建设公司医院网站
  • 雄安网建 网站建设订餐网站建设
  • 广州视频网站建站公司网站 体系