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

厦门同安区建设局网站建设网站如何挂到网上

厦门同安区建设局网站,建设网站如何挂到网上,wordpress 小说 主题,18+网站推广上一篇:Linux–多路转接之select epoll epoll 是 Linux 下多路复用 I/O 接口 select/poll 的增强版本#xff0c;它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统 CPU 利用率。它是 Linux 下多路复用 API 的一个选择#xff0c;相比 select 和 poll#xff0c… 上一篇:Linux–多路转接之select epoll epoll 是 Linux 下多路复用 I/O 接口 select/poll 的增强版本它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统 CPU 利用率。它是 Linux 下多路复用 API 的一个选择相比 select 和 pollepoll 提供了更高的性能并且使用起来也更加方便。 epoll的工作原理 eventpoll框架的核心在于它能够高效地处理多个文件描述符上的事件避免了传统I/O多路复用机制如select和poll中的轮询开销。eventpoll通过以下方式实现 注册文件描述符当文件描述符被注册到eventpoll时会创建一个epitemeventpoll item结构体用于表示该文件描述符及其关心的事件类型。这个epitem会被插入到eventpoll的红黑树rbtree中以便快速查找和管理。等待事件发生通过调用epoll_wait()系统调用应用程序会在eventpoll的等待队列wq上等待。此时指定的回调函数是default_wake_function用于在事件发生时唤醒等待的线程。事件通知当被监测的文件描述符上有事件发生时会调用ep_poll_callback()回调函数将相应的epitem插入到eventpoll的就绪链表rdllist中。epoll_wait()会从这个链表中取出epitem并将对应的事件通知给应用程序。 注意以上操作均有系统自主完成 epoll 的相关系统调用 epoll_create() 创建一个 epoll 的句柄. #include sys/epoll.h int epoll_create(int size);size 参数用于告诉内核这个监听列表epoll 实例打算同时监视多少个文件描述符。 返回值 如果调用成功epoll_create 返回一个新的文件描述符该描述符用于后续的 epoll_ctl()和 epoll_wait()调用。 如果调用失败则返回 -1并设置 errno 以指示错误原因。 epoll_ctl() 允许程序在 epoll 实例中添加、修改或删除文件描述符file descriptors的监听事件. #include sys/epoll.h int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);参数说明 epfd由 epoll_create () 函数生成的 epoll 实例的文件描述符。op指定要执行的操作常用的值包括 EPOLL_CTL_ADD向 epoll 实例注册新的文件描述符和事件。 EPOLL_CTL_MOD修改已注册的文件描述符的事件。 EPOLL_CTL_DEL从 epoll 实例中删除一个文件描述符。fd要操作的目标文件描述符即要注册、修改或删除的文件描述符。event指向 struct epoll_event 结构体的指针该结构体包含了要注册或修改的事件信息。对于 EPOLL_CTL_DEL 操作该参数可以为 NULL。 typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64; } epoll_data_t; struct epoll_event { uint32_t events; /* 事件类型 */ epoll_data_t data; /* 与事件相关的数据 */ }; events这是一个位掩码用于指示发生的事件类型。常见的事件类型包括 EPOLLIN表示对应的文件描述符可以进行读操作。 EPOLLOUT表示对应的文件描述符可以进行写操作。 EPOLLERR表示发生错误。 EPOLLHUP表示挂起hang up事件比如对端关闭了连接。 EPOLLET将事件设置为边缘触发Edge Triggered模式这是与水平触发Level Triggered模式相对的一种触发模式。 EPOLLONESHOT:用于确保事件被触发一次后除非再次使用 epoll_ctl 重新注册否则不再接收该事件。 data这是一个联合体可以存储与事件相关的数据。它提供了多种方式来关联事件和特定的数据或文件描述符 ptr可以指向任意类型的数据通常用于存储用户自定义的数据结构指针。 fd直接存储文件描述符的值当只需要管理文件描述符时这种方式更为直接(常用)。 u32 和 u64分别提供了32位和64位的无符号整数存储这些字段可以用来存储特定的值或标识符。 epoll_wait() 程序调用 epoll_wait 时它会阻塞当前线程直到注册在 epoll 实例上的文件描述符上有事件发生或者超时时间到达。 #include sys/epoll.h int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);参数说明 epfd由 epoll_create 函数生成的 epoll 实例的文件描述符。events指向 struct epoll_event 数组的指针用于存储发生的事件。当 epoll_wait 返回时该数组将被填充有发生事件的文件描述符和事件类型的信息。maxevents指定 events 数组的最大长度即 epoll_wait 一次可以处理的最大事件数。timeout指定等待 I/O 事件发生的超时时间毫秒。如果设置为 -1则 epoll_wait 将无限期地等待直到有事件发生。如果设置为 0则 epoll_wait 将立即返回无论是否有事件发生。如果设置为一个正整数则 epoll_wait 将等待指定的毫秒数如果在这段时间内有事件发生则返回否则返回 0表示超时。 返回值 成功时epoll_wait 返回发生事件的文件描述符数量。如果返回 0则表示在指定的超时时间内没有事件发生。如果发生错误epoll_wait 返回 -1并设置 errno 以指示错误原因。 epoll的工作方式 水平触发Level Triggered, LT 工作原理在水平触发模式下只要被监控的文件描述符上有可读写事件发生即数据到达但未被读取或可写空间可用但未被写入epoll_wait就会通知用户程序。 如果数据到达但是没有被读取或者可写空间可用但是没有被写入epoll_wait会再次通知用户程序直到相应的操作被执行。 特点 通知次数只要条件满足就会不断地通知。读写策略可以更灵活地处理读写不需要连续读取或写入直到遇到错误。效率由于频繁的通知可能会引起较多的上下文切换影响效率。编程复杂度相对容易理解和使用。 边缘触发Edge Triggered, ET 工作原理边缘触发模式是一种更高效的触发方式。在这种模式下epoll_wait仅在状态变化时通知用户程序一次比如从无数据到有数据或者从不可写变为可写。 当收到一个可读事件时需要一直读取数据直到返回EAGAIN错误表示没有更多数据可读。同样对于可写事件需要一直写入数据直到不能再写入为止。 知次数只在状态发生变化时通知一次。 读写策略读操作需要一直进行直到遇到EAGAIN错误写操作也是如此需要一直写直到无法继续写入。 效率减少了系统调用的次数提高了应用程序的效率。 编程复杂度要求程序必须更加小心地处理事件以避免错过任何事件这使得编程变得更加复杂。 主要区别 .水平触发LT边缘触发ET通知次数只要条件满足就会不断地通知只在状态发生变化时通知一次读写策略可以更灵活地处理读写读操作需要一直进行直到遇到EAGAIN错误写操作也是如此效率可能会引起较多的上下文切换影响效率减少了系统调用的次数提高了应用程序的效率编程复杂度相对容易理解和使用要求程序必须更加仔细地处理事件以避免错过任何事件编程复杂度高 epoll_server实例LT方式 我们将对上一篇的select_server进行一定的修改即可 epollServer.hpp #pragma once #include iostream #include string #include memory #include sys/epoll.h #include InetAddr.hpp #include Socket.hpp #include Log.hppusing namespace socket_ns;class EpollServer {const static int gnum 64; public:EpollServer(uint16_t port 8080): _port(port),_listensock(std::make_uniqueTcpSocket()),_epfd(-1){// 1. 创建listensockInetAddr addr(0, _port);//0表示任意ip_listensock-BuildListenSocket(addr);// 2. 创建epoll模型_epfd ::epoll_create(128);//返回值是epoll的fdif (_epfd 0){LOG(FATAL, epoll_create error\n);exit(5);}LOG(DEBUG, epoll_create success, epfd: %d\n, _epfd);// 3. 只有一个listensock, listen sock 关心的事件读事件struct epoll_event ev; //结构体包含事件的信息ev.events EPOLLIN;//事件可读ev.data.fd _listensock-SockFd(); //将listenfd放入到信息中epoll_ctl(_epfd, EPOLL_CTL_ADD, _listensock-SockFd(), ev);}//对事件的处理void handlerEvent(int num){for (int i 0; i num; i)//可处理多个事件{// 逐一将事件取出uint32_t revents _revs[i].events;int sockfd _revs[i].data.fd;// 读事件就绪if (revents EPOLLIN){if (sockfd _listensock-SockFd())//监听fd表示将创建连接fd{InetAddr clientaddr;int newfd _listensock-Accepter(clientaddr); // 不会被阻塞事件已知被响应if (newfd 0)continue;// 获取新链接成功struct epoll_event ev;ev.events EPOLLIN;ev.data.fd newfd;epoll_ctl(_epfd, EPOLL_CTL_ADD, newfd, ev);//将新事件添加到epoll中LOG(DEBUG, _listensock ready, accept done, epoll_ctl done, newfd is: %d\n, newfd);}else//表示连接的fd有事情发生{char buffer[1024];ssize_t n ::recv(sockfd, buffer, sizeof(buffer), 0); //接收客户端数据if (n 0){LOG(DEBUG, normal fd %d ready, recv begin...\n, sockfd);buffer[n] 0;std::cout client say# buffer std::endl;std::string echo_string server echo# ;echo_string buffer;::send(sockfd, echo_string.c_str(), echo_string.size(), 0);//将结果返回}else if (n 0)//表示连接已被断开没有断开无数据传输将阻塞于epoll{LOG(DEBUG, normal fd %d close, me too!\n, sockfd);// 对端连接关闭了::epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr);::close(sockfd);}else{::epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr); // 这里表示将epoll中的sockfd删除::close(sockfd);//而fd是拷贝进去的只是将拷贝在epoll中的fd擦除对应的fd事件还没有被关闭}}}}}//循环执行void Loop(){int timeout -1;//表示epoll阻塞等待直到有事件发生while (true){int n ::epoll_wait(_epfd, _revs, gnum, timeout);//用于等待事件的发生switch (n){case 0://规定时间内无事件发生LOG(DEBUG, epoll_wait timeout...\n);break;case -1://发生错误LOG(DEBUG, epoll_wait failed...\n);break;default://有事件发生LOG(DEBUG, epoll_wait haved event ready..., n : %d\n, n);handlerEvent(n);break;}}}~EpollServer(){_listensock-Close();//关闭listen_fdif (_epfd 0)//关闭epoll的fd::close(_epfd);} private:uint16_t _port; //端口号std::unique_ptrSocket _listensock; //监听sockint _epfd; //epoll的fdstruct epoll_event _revs[gnum];//事件数组存储对应事件 }; _epfd: epoll是Linux底层中一种高效的I/O多路复用机制所以也是属于一种事件需要在用户层创建对应的文件描述符用于表示对epoll的创建 _revs : 虽然在底层有红黑树来进行存储对应的事件但是在用户层是无法了解到底层的存储执行的因为epoll的底层全由系统来完成的用户无法操作所以还需要一个事件数组来存储对应的事件。 初始化 128是设置这次的最大事件管理数量相比于select来说他是无上限的比较灵活 对于事件的控制 将事件信息包含在ev结构体中即可 Loop: 这里我们将事件数组放入到函数中当 epoll_wait 返回时该数组将被填充有发生事件的文件描述符和事件类型的信息。这样就不用我们手动添加到事件数组中。 正是因为底层的红黑树会先存储着对应的事件信息当被监测的文件描述符上有事件发生时将相应的epitem插入到eventpoll的就绪链表rdllist中。epoll_wait()会从这个链表中取出epitem放到_revs中所以调用该函数会存到事件数组中。 handlerEvent: EPOLLIN是0x001, revents如果对应位上是可读的如0x003那么就能表示读事件就绪了 main.cc #include epollServer.hpp #include Log.hpp#include iostream #include memory// ./selectserver port int main(int argc, char *argv[]) {if (argc ! 2){std::cout Usage: argv[0] port std::endl;return 0;}uint16_t port std::stoi(argv[1]);EnableScreen();std::unique_ptrEpollServer svr std::make_uniqueEpollServer(port);svr-Loop();return 0; }注ET模式相对来说比较复杂需要涉及到非阻塞的程序等下一篇Reactor再详细展示。 epoll的优点 支持水平触发LT和边缘触发ET接口简单易用没有最大文件描述符数量的限制 select 和 poll 都有文件描述符数量的限制而 epoll 则没有。只管理“活跃”的连接epoll 会检查注册在其上的所有 socket只将那些真正活跃的 socket 返回给用户即减少了无效的等待时间。高效处理大量并发连接epoll能够高效地处理大量并发连接尤其适用于只有少量活跃连接的大量并发场景。它通过内核与用户空间共享一个事件表来跟踪所有需要监控的文件描述符当文件描述符的状态发生变化时内核会通知用户空间从而避免了传统方法中的线性扫描。提高CPU利用率epoll在等待事件就绪时如果就绪队列中没有事件会主动让出CPU从而提高了CPU的利用率。这使得epoll在处理大量并发连接时能够更加高效地利用系统资源。
http://www.w-s-a.com/news/622252/

相关文章:

  • 网站直播间 是怎么做的唐山论坛建站模板
  • 深圳洲聚网站建设wordpress 泛解析
  • 五金东莞网站建设技术支持wordpress 添加模板
  • 网站申请专利春节网页设计素材
  • 进网站备案md风格的wordpress主题
  • 如何建站网站十大免费建站app
  • 工作号做文案素材的网站晋城网站设计人
  • 建设部网站官网 施工许可怎样建网站 需要
  • 什么网站都能打开的浏览器同城小程序怎么推广
  • 在电脑上怎么做网站网址seo分析
  • 石家庄做网站网络公司电子商务营销推广
  • 网站开发 前端专做婚礼logo的网站
  • 同创企业网站建设拖拽建设网站源码
  • wordpress调用网站标题网站页面排版
  • 哈尔滨营销网站建设电子商城网站开发要多少钱
  • 免费织梦导航网站模板下载地址自己建站网站
  • 获取网站访客qq号码代码做抽奖网站违法吗
  • 湖南大型网站建设公司排名偷网站源码直接建站
  • 网站建设周期规划北京网站设计必看刻
  • 如何做自己的在线作品网站深圳网站设计公司的
  • 网站开发外包公司wordpress最简单模板
  • 湖南省建设人力资源网站wordpress主机pfthost
  • 淮安软件园哪家做网站各网站特点
  • 网站长尾关键词排名软件重庆荣昌网站建设
  • 建个商城网站多少钱茂名专业网站建设
  • 开通公司网站免费的网站app下载
  • 跨境电商网站模板wordpress壁纸
  • 国内做网站网站代理电子商务网站建设与维护概述
  • 如何做地方网站推广沈阳网势科技有限公司
  • 哈尔滨网站优化技术涵江网站建设