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

一个人做网站要多久阿里云申请域名

一个人做网站要多久,阿里云申请域名,南宁网络企业网站,手机网站优化公司文章目录 EpollPoller事件分发器类成员变量和成员函数解释私有的成员函数和成员变量成员函数 具体实现常量的作用构造函数和析构函数⭐️poll函数updateChannel函数removeChannel 函数removeChannel 和updateChannel⭐️fillActiveChannels 函数⭐️update 函数 总结 终于要开始… 文章目录 EpollPoller事件分发器类成员变量和成员函数解释私有的成员函数和成员变量成员函数 具体实现常量的作用构造函数和析构函数⭐️poll函数updateChannel函数removeChannel 函数removeChannel 和updateChannel⭐️fillActiveChannels 函数⭐️update 函数 总结 终于要开始我们的重点事件分发起和事件循环了在这里我们将揭开事件驱动的IO多路复用模型的神秘面纱 EpollPoller事件分发器类 成员变量和成员函数解释 这些都是在头文件中声明的我们可以先对类中封装的各个方法进行合理的研究和猜测。 私有的成员函数和成员变量 在这里我们简单介绍一下私有成员函数和成员变量 私有成员函数如下 void fillActiveChannels(int numEvents, ChannelList *activeChannels) const; void update(int operation, Channel *channel);fillActiveChannels()这里主要就是将 epoll_wait 返回的活跃事件填充到 activeChannels中。update()这里的根据操作类型添加、修改、删除调用epoll_ctl来更新epoll实例中的Channel对象。 在Channel类中我们也写了一个update它的具体实现是loop_-updateChannel(this);调用了EventLoop中的updateChannel所以我们有理由怀疑其中的updateChannel()就是在调用这里的update方法 私有成员变量 static const int kInitEventListSize 16; using EventList std::vectorepoll_event;int epollfd_; EventList events_;kInitEventListSize 初始事件列表大小。EventList 用于存储epoll事件的向量类型。int epollfd_ epoll实例的文件描述符。EventList events_ 存储从epoll_wait返回的事件列表。 成员函数 EPollPoller(EventLoop *Loop);~EPollPoller() override;//重写基类Poller的抽象方法Timestamp poll(int timeoutMs, ChannelList *activeChannels) override;void updateChannel(Channel *channel) override;void removeChannel(Channel *channel) override;Timestamp poll(int timeoutMs, ChannelList *activeChannels) 调用epoll_wait等待事件发生将活跃的事件填充到activeChannels中。 void updateChannel(Channel *channel) 更新或添加一个Channel对象到epoll实例中调用epoll_ctl。 void removeChannel(Channel *channel) 从epoll实例中移除一个Channel对象调用epoll_ctl。 具体实现 #include EpollPoller.h #include Logger.h #include Channel.h#include errno.h #include unistd.h #include strings.hconst int kNew -1; const int kAdded 1; const int kDeleted -1;EPollPoller::EPollPoller(EventLoop *loop) : Poller(loop), epollfd_(::epoll_create1(EPOLL_CLOEXEC)), events_(kInitEventListSize) { //创建了vectorepoll_eventsif (epollfd_ 0) LOG_FATAL(epoll_create error:%d\n, errno);}EPollPoller::~EPollPoller() {::close(epollfd_); }Timestamp EPollPoller::poll(int timeoutMs, ChannelList *activeChannels) {LOG_INFO(func%s fd total count:%lu \n, __FUNCTION__, channels_.size());int numEvents ::epoll_wait(epollfd_, *events_.begin(), static_castint(events_.size()), timeoutMs);int saveErrno errno;Timestamp now(Timestamp::now());if (numEvents 0) {LOG_INFO(%d events happened \n, numEvents);fillActiveChannels(numEvents, activeChannels);if (numEvents events_.size()) {events_.resize(events_.size() * 2);}} else if (numEvents 0) {LOG_DEBUG(%s timeout! \n, __FUNCTION__);} else {if (saveErrno ! EINTR) {errno saveErrno;LOG_ERROR(EPollPoller::poll() err!);}}return Timestamp(); }void EPollPoller::updateChannel(Channel *channel) {const int index channel-index();// LOG_INFO(func%s fd%d events%d index%d\n// , __FUNCTION__// , channel-fd// , channel-events()// , index)if (index kNew || index kDeleted) {if (index kNew) {int fd channel-fd();channels_[fd] channel;}channel-set_index(kAdded);update(EPOLL_CTL_ADD, channel);} else { //说明channel已经在Poller注册过了int fd channel-fd();if (channel-isNoneEvent()) {update(EPOLL_CTL_DEL, channel);channel-set_index(kDeleted);} else {update(EPOLL_CTL_MOD, channel);}} }//从poller中删除channel void EPollPoller::removeChannel(Channel *channel) {int fd channel-fd();channels_.erase(fd);LOG_INFO(func%s fd%d\n, __FUNCTION__, fd);int index channel-index();if (index kAdded) {update(EPOLL_CTL_DEL, channel);}channel-set_index(kNew); }//填写活跃的连接 void EPollPoller::fillActiveChannels(int numEvents, ChannelList *activeChannels) const {for (int i 0; i numEvents; i) {Channel *channel static_castChannel*(events_[i].data.ptr);channel-set_revents(events_[i].events);activeChannels-push_back(channel); //EventLoop就拿到了它的poller给它返回的所有发生事件的channel列表了} }//更新channel通道 epoll_ctl add/mod/del void EPollPoller::update(int operation, Channel *channel) {epoll_event event;bzero(event, sizeof event);int fd channel-fd();event.events channel-events();event.data.fd fd;event.data.ptr channel;if (::epoll_ctl(epollfd_, operation, fd, event) 0) {if (operation EPOLL_CTL_DEL) {LOG_ERROR(epoll_ctl del error:%d\n, errno);} else {LOG_FATAL(epoll_ctl add/mod error:%d\n, errno);}} }常量的作用 // channel未添加到poller中 const int kNew -1; // channel的成员index_ -1 // channel已添加到poller中 const int kAdded 1; // channel从poller中删除 const int kDeleted 2;他们主要用于表示 channel的状态在后续的方法具体实现中会体现到。 构造函数和析构函数 EPollPoller::EPollPoller(EventLoop *loop): Poller(loop), epollfd_(::epoll_create1(EPOLL_CLOEXEC)), events_(kInitEventListSize) // vectorepoll_event {if (epollfd_ 0){LOG_FATAL(epoll_create error:%d \n, errno);} }EPollPoller::~EPollPoller() {::close(epollfd_); } 构造函数创建一个epoll实例epollfd_随后我们需要初始化我们所关注的事件列表大小events_析构函数我们知道我们将所有监控的事件都委托给了内核的epoll实例来进行管理该实例底层是一颗红黑树。我们最后析构的时候可以直接关闭close就可以关闭所有网络IO的文件描述符了。 ⭐️poll函数 Timestamp EPollPoller::poll(int timeoutMs, ChannelList *activeChannels) {LOG_INFO(func%s fd total count:%lu \n, __FUNCTION__, channels_.size());int numEvents ::epoll_wait(epollfd_, *events_.begin(), static_castint(events_.size()), timeoutMs);int saveErrno errno;Timestamp now(Timestamp::now());if (numEvents 0) {LOG_INFO(%d events happened \n, numEvents);fillActiveChannels(numEvents, activeChannels);if (numEvents events_.size()) {events_.resize(events_.size() * 2);}} else if (numEvents 0) {LOG_DEBUG(%s timeout! \n, __FUNCTION__);} else {if (saveErrno ! EINTR) {errno saveErrno;LOG_ERROR(EPollPoller::poll() err!);}}return Timestamp(); }他就是实现我们多路分发的函数 poll 函数使用 epoll_wait 等待事件发生并将活跃的事件填充到 activeChannels 中。如果发生事件将这些事件填充到 activeChannels并在必要时扩展事件列表。返回当前的时间戳主要是为了后续方便打日志和进行管理。 updateChannel函数 void EPollPoller::updateChannel(Channel *channel) {const int index channel-index();LOG_INFO(func%s fd%d events%d index%d \n, __FUNCTION__, channel-fd(), channel-events(), index);if (index kNew || index kDeleted){int fd channel-fd();if (index kNew){channels_[fd] channel;}channel-set_index(kAdded);update(EPOLL_CTL_ADD, channel);}else{int fd channel-fd();if (channel-isNoneEvent()){update(EPOLL_CTL_DEL, channel);channel-set_index(kDeleted);}else{update(EPOLL_CTL_MOD, channel);}} }updateChannel 函数根据 Channel 的当前状态新添加或已删除来决定是否添加或更新 epoll 实例中的事件该函数肯定会被EventLoop封装然后再由Channel自己来进行调用。如果是新添加的 Channel则在 epoll 中注册该文件描述符。如果 Channel 没有感兴趣的事件则将其从 epoll 中删除。 removeChannel 函数 void EPollPoller::removeChannel(Channel *channel) {int fd channel-fd();LOG_INFO(func%s fd%d\n, __FUNCTION__, fd);int index channel-index();if (index kAdded){update(EPOLL_CTL_DEL, channel);}channel-set_index(kNew); }removeChannel 函数将 Channel 从 epoll 实例中删除并更新其状态。这一看就是我们的EventLoop需要调用的函数。 removeChannel 和updateChannel 从这两个函数理我们可以看出他们其实是为EventLoop提供操作Channel的方法。从代码的具体实现细节来看我们可以领略到 channel 为什么要设置一个 index_ 标志主要就是为了实现channel的复用我们总不能每次有新连接都新建一个channel连接断开就删除channel吧 ⭐️fillActiveChannels 函数 void EPollPoller::fillActiveChannels(int numEvents, ChannelList *activeChannels) const {for (int i 0; i numEvents; i){Channel *channel static_castChannel*(events_[i].data.ptr);channel-set_revents(events_[i].events);activeChannels-push_back(channel);} }fillActiveChannels 函数将 epoll_wait 返回的所有活跃事件填充到 activeChannels 列表中。 然手我们介绍一下 event.data我们将已经被激活的event直接拿到手这里就需要用到我们的event.data.ptr: data字段是一个联合体具体结构包含了我们常用的int fd和void *ptr ptr 是一个通用指针可以用来指向任何类型的数据。它通常用于关联用户自定义的数据结构(这里是我们的Channel*)以便在事件触发时可以快速访问这些数据。例如你可以将 ptr 设置为你的应用程序中某个特定对象的指针当对应的文件描述符触发事件时你的应用程序可以通过 ptr 直接访问到这个对象。 然后调用channel的set_revents方法可以将已经被激活的事件直接初始化到我们的channel中。 随后把 channel 推到我们的 activeChannels ⭐️update 函数 void EPollPoller::update(int operation, Channel *channel) {epoll_event event;bzero(event, sizeof event);int fd channel-fd();event.events channel-events();event.data.fd fd; event.data.ptr channel;if (::epoll_ctl(epollfd_, operation, fd, event) 0){if (operation EPOLL_CTL_DEL){LOG_ERROR(epoll_ctl del error:%d\n, errno);}else{LOG_FATAL(epoll_ctl add/mod error:%d\n, errno);}} }update 函数根据操作类型添加、修改或删除调用 epoll_ctl 来更新 epoll 实例中的 Channel。 其实说白了update就是用来封装epoll_ctl的。 该函数被 EPollPoller::removeChannel、EPollPoller::updateChannel调用用来更新Channel的封装的fd以及其需要监控的相关事件。 总结 EPollPoller 类实现了基于 epoll 的 I/O 多路复用通过监控多个文件描述符上的事件并在事件发生时通知相应的 Channel 对象来处理事件。通过实现这些函数EPollPoller 能够高效地管理和分发事件。 下一节我们将讲解EventLoop类的具体实现
http://www.hkea.cn/news/14583446/

相关文章:

  • 网站怎么做收入工信部网站备案登陆
  • 郑州专业做网站多少钱班级优化大师是干什么用的
  • 网站建设不完整什么意思石家庄是几线城市
  • 网站搜索显示图片微信商城怎么找
  • 外链网站 英文东乡族网站建设
  • 中国互联网头部企业北京百度搜索排名优化
  • 基于C 的网站开发源码靖江网站定制
  • 昆山网站建设书生商友官方网站开发与定制
  • 东莞建站网站怎么查询网站的域名
  • 如何免费申请公司网站wordpress手册插件
  • 厦门满山红网站建设Wordpress好看模板
  • 网站收费系统平台wordpress 前台文章
  • 岳阳市网站建设推广如何做好电商
  • 微信小程序开发网站建设绵阳东原建设工程有限公司网站
  • lol网站模板开通网站费用怎么做分录
  • 在线制作网站乔拓云dede如何制作手机网站
  • 网站新闻中心模版东平网站建设
  • 网站建设第三方验收收费标准电子宣传册如何制作
  • 手机微网站模板中国软件外包公司排行
  • 临沧永德网站建设电子商务公司管理咨询服务合同范本
  • 广州seo网站推广公司做网站能够带来的好处
  • 杭州网站建设方案优化网站后台上传新闻
  • 晋江网站有什么职业做学习网站开发教程
  • 做路牌的网站做网站赚几百万
  • 泉州专业做网站app网站
  • 苏州 网站设计it外包服务平台
  • 无锡外贸网站建设wordpress分类目录样式
  • 广州智能建站软件关于化妆品网站成功案例
  • 河南省建设厅网站资质平移办法网页后台常用设计尺寸
  • 做网站所需要的代码6网站建设dream