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

建设景区网站要有的内容天津网站建设定做

建设景区网站要有的内容,天津网站建设定做,最新wordpress漏洞,wordpress 默认评论1 libev libev所实现的功能就是一个强大的reactor,可能notify事件主要包括下面这些#xff1a; ev_io // IO可读可写ev_stat // 文件属性变化ev_async // 激活线程ev_signal // 信号处理ev_timer // 定时器ev_periodic // 周期任务ev_child // 子进程状态变化ev_fork // 开辟进…   1 libev libev所实现的功能就是一个强大的reactor,可能notify事件主要包括下面这些 ev_io // IO可读可写ev_stat // 文件属性变化ev_async // 激活线程ev_signal // 信号处理ev_timer // 定时器ev_periodic // 周期任务ev_child // 子进程状态变化ev_fork // 开辟进程ev_cleanup // event loop退出触发事件ev_idle // 每次event loop空闲触发事件ev_embed // TODO(zhangyan04):I have no idea.ev_prepare // 每次event loop之前事件ev_check // 每次event loop之后事件 1.1 About The Code 代码风格相当严谨而且排版也非常工整并且从域名看出作者是德国人。但是内部使用了大量的宏造成阅读代码并不是非常方便。 并且从代码角度分析应该是一开始支持有一个默认的event_loop,但是随着多核产生实际应用中可能会使用到多个event_loop, 猜想作者应该是为了方便的话使用了很多宏进行替换。允许使用多个event_loop的宏是EV_MULTIPLICITY.比如下面这段代码 void noinline ev_io_start (EV_P_ ev_io *w) {int fd w-fd;if (expect_false (ev_is_active (w)))return;assert ((libev: ev_io_start called with negative fd, fd 0));assert ((libev: ev_io_start called with illegal event mask, !(w-events ~(EV__IOFDSET | EV_READ | EV_WRITE))));EV_FREQUENT_CHECK;ev_start (EV_A_ (W)w, 1);array_needsize (ANFD, anfds, anfdmax, fd 1, array_init_zero);wlist_add (anfds[fd].head, (WL)w);fd_change (EV_A_ fd, w-events EV__IOFDSET | EV_ANFD_REIFY);w-events ~EV__IOFDSET;EV_FREQUENT_CHECK; }初次阅读这个代码会觉得非常难懂。 宏说明定义EV_Pevent parameterstruct ev_loop *loopEV_P_ EV_P,EV_Aevent argumentloopEV_A_ EV_A, 然后很多变量只要是ev_loop成员的话都被封装成为了宏。比如代码里面的anfds,实际上的宏定义是 #define anfds ((loop)-anfds)事实上一个ev_loop里面的字段是相当多的不过也很正常本身就是一个强大的reactor.但是这造成一个直接后果 就是对于想要了解ev_loop的全貌比较困难所以想要彻底地了解libev也比较麻烦所以我们只能够从应用层面来尝试了解它。 1.2 EventLoop 首先我们关注一下reactor本身。在libev下面reactor对象称为event_loop.event_loop允许动态创建和销毁并且允许绑定自定义数据 struct ev_loop * ev_loop_new (unsigned int flags); void ev_loop_destroy (EV_P); void ev_set_userdata (EV_P_ void *data); void *ev_userdata (EV_P);我们这里主要关注一下flags.这里面主要是选择使用什么backend来进行poll操作可以选择的有 EVBACKEND_SELECTEVBACKEND_POLLEVBACKEND_EPOLL // 通常我们选择这个EVBACKEND_KQUEUEEVBACKEND_DEVPOLLEVBACKEND_PORT但是还有三个比较重要选项 EVFLAG_NOINOTIFY // 不适用inofity调用来使用ev_stat.这样可以减少fd使用。EVFLAG_SIGNALFD // 使用signalfd来检测信号是否发生同样这样可以减少fd使用。大部分时候我们使用EVFLAG_AUTO(0)一般就足够满足需求了从代码角度来看如果支持epoll的话那么首先会选择epoll. 因为在watcher的回调函数里面是可以知道当前event_loop的这样就可以获得自定义数据。然后我们看看这个event_loop如何运行和停止的 void ev_run (EV_P_ int flags); void ev_break (EV_P_ int how);同样我们这里比较关注flags和how这两个参数。flags有下面这几个 0.默认值。一直循环进行处理直到外部引用计数0或者是显示退出。EVRUN_NOWAIT.运行一次poll时候不会等待。如果有pending事件进行处理否则立即返回。EVRUN_ONCE.运行一次poll时候会等待至少一个event发生处理完成之后返回。而how有下面这几个 EVBREAK_ONE.只是退出一次ev_run这个调用。通常来说使用这个就可以了。EVBREAK_ALL.退出所有的ev_run调用。这种情况存在于ev_run在pengding处理时候会递归调用。在backend/epoll底层每次epoll_wait时候libev提供了接口回调可以在epoll_wait前后调用 void ev_set_loop_release_cb (loop, void (*release)(EV_P), void (*acquire)(EV_P)) static void epoll_poll (EV_P_ ev_tstamp timeout) {/* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below *//* the default libev max wait time, however. */EV_RELEASE_CB;eventcnt epoll_wait (backend_fd, epoll_events, epoll_eventmax,epoll_epermcnt ? 0 : ev_timeout_to_ms (timeout));EV_ACQUIRE_CB; }在event_loop里面我们还关心一件事情就是每次event_loop轮询的时间长短。通常来说这个不会是太大问题但是在高性能情况下面我们需要设置 void ev_set_io_collect_interval (EV_P_ ev_tstamp interval); void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval);在ev_run里面有使用这些参数的代码比较麻烦。但是大意是这样如果我们这是了timeout_interval的话那么我们每次检查timeout时间的话必须 在timeout_interval使用这段时间ev_sleep.但是这个又会影响到io_interval,所以内部做了一些换算换算的结果作为epoll_wait超时时间。 不过同样在大部分时候我们不需要关心它默认时候是0.0,系统会使用最快的响应方式来处理。 1.3 Watcher 然后我们关心一下EventHandler.在libev下面watcher相当于EventHandler这么一个概念通常里面会绑定fd回调函数以及我们需要关注的事件。 然后一旦触发事件之后会触发我们使用的回调函数回调函数参数通常有reactor,watcher以及触发的事件。这里不打算重复文档里面的watcher 相关的内容和对应的API,但是对于某些内容的话可能会提到并且附带一些注释。之前我们还是看看通用过程这里使用TYPE区分不同类型watcher. typedef void (*)(struct ev_loop *loop, ev_TYPE *watcher, int revents) callback; // callback都是这种类型 ev_init (ev_TYPE *watcher, callback); // 初始化watcher ev_TYPE_set (ev_TYPE *watcher, [args]); // 设置watcher ev_TYPE_init (ev_TYPE *watcher, callback, [args]); // 通常使用这个函数最方便初始化和设置都在这里 ev_TYPE_start (loop, ev_TYPE *watcher); // 注册watcher ev_TYPE_stop (loop, ev_TYPE *watcher); // 注销watcher ev_set_priority (ev_TYPE *watcher, int priority); // 设置优先级 ev_feed_event (loop, ev_TYPE *watcher, int revents); // 这个做跨线程通知非常有用相当于触发了某个事件。 bool ev_is_active (ev_TYPE *watcher); // watcher是否active. bool ev_is_pending (ev_TYPE *watcher); // watcher是否pending. int ev_clear_pending (loop, ev_TYPE *watcher); // 清除watcher pending状态并且返回事件wacther的状态有下面这么几种 initialiased.调用init函数初始化active.调用start进行注册pending.已经触发事件但是没有处理inactive.调用stop注销。这个状态等同于initialised这个状态。其实关于每个watcher具体是怎么实现的没有太多意思因为大部分现有代码都差不多。会在下一节说说内部数据结构是怎么安排的 了解内部数据结构以及过程之后很多问题就可以避免了比如The special problem of disappearing file descriptors这类问题。 1.4 How it works 1.4.1 ev_run 最主要的还是看看ev_run这个部分代码。我们不打算仔细阅读只是看看梗概然后大体分析一下数据结构应该怎么样的 void ev_run (EV_P_ int flags) {assert ((libev: ev_loop recursion during release detected, loop_done ! EVBREAK_RECURSE));loop_done EVBREAK_CANCEL;EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */do{if (expect_false (loop_done))break;/* update fd-related kernel structures */fd_reify (EV_A);/* calculate blocking time */{ev_tstamp waittime 0.;ev_tstamp sleeptime 0.;/* remember old timestamp for io_blocktime calculation */ev_tstamp prev_mn_now mn_now;/* update time to cancel out callback processing overhead */time_update (EV_A_ 1e100);if (expect_true (!(flags EVRUN_NOWAIT || idleall || !activecnt))){waittime MAX_BLOCKTIME;if (timercnt){ev_tstamp to ANHE_at (timers [HEAP0]) - mn_now backend_fudge;if (waittime to) waittime to;}/* dont let timeouts decrease the waittime below timeout_blocktime */if (expect_false (waittime timeout_blocktime))waittime timeout_blocktime;/* extra check because io_blocktime is commonly 0 */if (expect_false (io_blocktime)){sleeptime io_blocktime - (mn_now - prev_mn_now);if (sleeptime waittime - backend_fudge)sleeptime waittime - backend_fudge;if (expect_true (sleeptime 0.)){ev_sleep (sleeptime);waittime - sleeptime;}}}assert ((loop_done EVBREAK_RECURSE, 1)); /* assert for side effect */backend_poll (EV_A_ waittime);assert ((loop_done EVBREAK_CANCEL, 1)); /* assert for side effect *//* update ev_rt_now, do magic */time_update (EV_A_ waittime sleeptime);}/* queue pending timers and reschedule them */timers_reify (EV_A); /* relative timers called last */EV_INVOKE_PENDING;}while (expect_true (activecnt !loop_done !(flags (EVRUN_ONCE | EVRUN_NOWAIT))));if (loop_done EVBREAK_ONE)loop_done EVBREAK_CANCEL; }我们可以总结一下大致步骤其实和大部分的event loop写出来差不多。 首先触发那些已经pending的watchers.判断是否loop_donefd_reify.这个后面会单独说。计算出waittime并且进行必要的sleep.backend_poll开始轮询,并且整理好pending事件timers_reify.这个和fd_reify不同调用EV_INVOKE_PENDING来触发pending的io事件非常简单。接下来我们看看fd_reify,backend_poll,timers_reify以及EV_INVOKE_PENDING. 1.4.2 fd_reify 下面是fd_reify代码片段.可以看出这个部分就是在修改fd关注的events。 inline_size void fd_reify (EV_P) {int i;for (i 0; i fdchangecnt; i){int fd fdchanges [i];ANFD *anfd anfds fd;ev_io *w;unsigned char o_events anfd-events;unsigned char o_reify anfd-reify;anfd-reify 0;/*if (expect_true (o_reify EV_ANFD_REIFY)) probably a deoptimisation */{anfd-events 0;for (w (ev_io *)anfd-head; w; w (ev_io *)((WL)w)-next)anfd-events | (unsigned char)w-events;if (o_events ! anfd-events)o_reify EV__IOFDSET; /* actually | */}if (o_reify EV__IOFDSET)backend_modify (EV_A_ fd, o_events, anfd-events);}fdchangecnt 0; }而这个fdchanges这个是在哪里调用的呢。我们可以看到就是在ev_io_start这个部分。也就是说如果我们想要修改 fd关注事件的话我们必须显示地ev_io_stop掉然后修正之后重新ev_io_start.底层调用fd_change的话底层维护 数组fdchanges来保存发生events变动的fd. void noinline ev_io_start (EV_P_ ev_io *w) {int fd w-fd;if (expect_false (ev_is_active (w)))return;assert ((libev: ev_io_start called with negative fd, fd 0));assert ((libev: ev_io_start called with illegal event mask, !(w-events ~(EV__IOFDSET | EV_READ | EV_WRITE))));EV_FREQUENT_CHECK;ev_start (EV_A_ (W)w, 1);array_needsize (ANFD, anfds, anfdmax, fd 1, array_init_zero);wlist_add (anfds[fd].head, (WL)w);fd_change (EV_A_ fd, w-events EV__IOFDSET | EV_ANFD_REIFY);w-events ~EV__IOFDSET;EV_FREQUENT_CHECK; }inline_size void fd_change (EV_P_ int fd, int flags) {unsigned char reify anfds [fd].reify;anfds [fd].reify | flags;if (expect_true (!reify)){fdchangecnt;array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2);fdchanges [fdchangecnt - 1] fd;} }1.4.3 backend_poll backend_poll底层支持很多poll实现我们这里仅仅看ev_epoll.c就可以.代码在这里面我们不列举了 如果某个fd触发事件的话那么最终会调用fd_event(EV_A_,fd,event)来进行通知。所以我们看看fd_event. inline_speed void fd_event_nocheck (EV_P_ int fd, int revents) {ANFD *anfd anfds fd;ev_io *w;for (w (ev_io *)anfd-head; w; w (ev_io *)((WL)w)-next){int ev w-events revents;if (ev)ev_feed_event (EV_A_ (W)w, ev);} } void noinline ev_feed_event (EV_P_ void *w, int revents) {W w_ (W)w;int pri ABSPRI (w_);if (expect_false (w_-pending))pendings [pri][w_-pending - 1].events | revents;else{w_-pending pendingcnt [pri];array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_-pending, EMPTY2);// set the watcher and revents.pendings [pri][w_-pending - 1].w w_;pendings [pri][w_-pending - 1].events revents;} }可以看到底层是一个ANFD的数组根据fd进行偏移。如果fd过大的话似乎会影响性能没有hpserver里面的demuxtable实现方式好。 然后得到这个fd下面所有的watcher,然后在loop-pendings里面记录所有这些触发的watcher. 1.4.4 timers_reify 其中HEAP0就是最小堆下标。如果repeat的话说明需要重复发生那么就会重新调整时间戳如果不是repeat的话 那么内部会调用ev_timer_stop这个方法将这个计时器移除。所有的定时任务都通过feed_reverse添加。feed_reverse 内部是维护一个动态数组来保存所有的定时器任务然后在feed_reverse_done里面遍历这些任务来触发这些定时器任务。 inline_size void timers_reify (EV_P) {EV_FREQUENT_CHECK;if (timercnt ANHE_at (timers [HEAP0]) mn_now){do{ev_timer *w (ev_timer *)ANHE_w (timers [HEAP0]);/*assert ((libev: inactive timer on timer heap detected, ev_is_active (w)));*//* first reschedule or stop timer */if (w-repeat){ev_at (w) w-repeat;if (ev_at (w) mn_now)ev_at (w) mn_now;assert ((libev: negative ev_timer repeat value found while processing timers, w-repeat 0.));ANHE_at_cache (timers [HEAP0]);downheap (timers, timercnt, HEAP0);}elseev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */EV_FREQUENT_CHECK;feed_reverse (EV_A_ (W)w);}while (timercnt ANHE_at (timers [HEAP0]) mn_now);feed_reverse_done (EV_A_ EV_TIMER);} }1.4.5 EV_INVOKE_PENDING 这个宏最终调用的函数就是下面这个遍历所有的pendings事件并且逐一触发。 void noinline ev_invoke_pending (EV_P) {int pri;for (pri NUMPRI; pri--; )while (pendingcnt [pri]){ANPENDING *p pendings [pri] --pendingcnt [pri];p-w-pending 0;EV_CB_INVOKE (p-w, p-events);EV_FREQUENT_CHECK;} }1.5 Example 尝试编写一个简单的带有超时的echo-server和echo-client就发现其实还有非常多的其他的工作量比如buffer的管理状态机实现等。 所以我没有写出一个完整的example,只是简单地写了假设echo-client连接上server的话就简单地打印链接信息并且关闭。 1.5.1 common.h #ifndef _COMMON_H_ #define _COMMON_H_#include unistd.h #include fcntl.h #include sys/types.h #include sys/socket.h #include arpa/inet.h #include strings.h #include cstdlib #include cstdio #include cstddef #include stringnamespace common{#define D(exp,fmt,...) do { \if(!(exp)){ \fprintf(stderr,fmt,##__VA_ARGS__); \abort(); \} \}while(0)static void setnonblock(int fd){fcntl(fd,F_SETFL,fcntl(fd,F_GETFL) | O_NONBLOCK); } static void setreuseaddr(int fd){int ok1;setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,ok,sizeof(ok)); }static void setaddress(const char* ip,int port,struct sockaddr_in* addr){bzero(addr,sizeof(*addr));addr-sin_familyAF_INET;inet_pton(AF_INET,ip,(addr-sin_addr));addr-sin_porthtons(port); }static std::string address_to_string(struct sockaddr_in* addr){char ip[128];inet_ntop(AF_INET,(addr-sin_addr),ip,sizeof(ip));char port[32];snprintf(port,sizeof(port),%d,ntohs(addr-sin_port));std::string r;rr(ip:port);return r; }static int new_tcp_server(int port){int fdsocket(AF_INET,SOCK_STREAM,IPPROTO_TCP);D(fd0,socket failed(%m)\n);setnonblock(fd);setreuseaddr(fd);sockaddr_in addr;setaddress(0.0.0.0,port,addr);bind(fd,(struct sockaddr*)addr,sizeof(addr));listen(fd,64); // backlog 64return fd; }static int new_tcp_client(const char* ip,int port){int fdsocket(AF_INET,SOCK_STREAM,IPPROTO_TCP);setnonblock(fd);sockaddr_in addr;setaddress(ip,port,addr);connect(fd,(struct sockaddr*)(addr),sizeof(addr));return fd; }}; // namespace common#endif // _COMMON_H_1.5.2 echo-client.cc #include ev.h #include common.hstatic void do_connected(struct ev_loop* reactor,ev_io* w,int events){close(w-fd);ev_break(reactor,EVBREAK_ALL); }int main(){struct ev_loop* reactorev_loop_new(EVFLAG_AUTO);int fdcommon::new_tcp_client(127.0.0.1,34567);ev_io io;ev_io_init(io,do_connected,fd,EV_WRITE);ev_io_start(reactor,io);ev_run(reactor,0);close(fd);ev_loop_destroy(reactor);return 0; } 1.5.3 echo-server.cc #include ev.h #include common.hstatic void do_accept(struct ev_loop* reactor,ev_io* w,int events){struct sockaddr_in addr;socklen_t addr_sizesizeof(addr);int connaccept(w-fd,(struct sockaddr*)addr,addr_size);std::string rcommon::address_to_string(addr);fprintf(stderr,accept %s\n,r.c_str());close(conn); }int main(){struct ev_loop* reactorev_loop_new(EVFLAG_AUTO);int fdcommon::new_tcp_server(34567);ev_io w;ev_io_init(w,do_accept,fd,EV_READ);ev_io_start(reactor,w);ev_run(reactor,0);close(fd);ev_loop_destroy(reactor); } 本文来自 http://www.dirlt.com/libev.html   主页http://software.schmorp.de/pkg/libev.html 文档http://software.schmorp.de/pkg/libev.html  转载于:https://www.cnblogs.com/zhangzhang/archive/2013/01/07/2848924.html
http://www.pierceye.com/news/133631/

相关文章:

  • 深圳做棋牌网站建设哪家技术好建设一个网站的规划
  • 网站开发流程比较合理网站已经申请了域名 接下来怎么
  • 校园电商平台网站建设网站网址模板
  • 沈阳有资质做网站的公司温州做网站定制
  • wordpress codex网站seo和sem是什么意思
  • 建网站平台哪家好装修设计软件app排行
  • 网站开发文档撰写企业管理培训课程图片
  • 网站开发公司资质wordpress文章管理模板
  • 建筑网站知识大全江苏有哪些网站建设的公司
  • 江汉网站建设用js做网站登录
  • wordpress做购物网站河南省建设工程造价协会网站
  • wex5可以做网站吗爱射影院网站建设中
  • 网站建设多选题百度文库做好中心网站建设工作总结
  • 网站开发都用phpwordpress文章内图片幻灯片
  • 岳阳网站建设企业绿色大气漂亮dedecms茶叶企业网站
  • 网站建设使用虚拟主机的优点与缺点做百科网站
  • 网站被墙是谁做的电影网站模板
  • 合肥建设网官方网站网页设计网站制作公司
  • 外贸网站建设评价网站的营销方案
  • 邯郸专业做wap网站中国设计网址导航
  • 邯郸移动网站建设价格官方网站车联网是谁做
  • 哪个网站可以做高像素动图个人网站排版设计
  • 多少网站域名采用中文做一个电子商务网站在哪里做
  • 家装设计学校沈阳网站建设优化企业
  • 网站开发公司售后服务触屏端网站开发
  • 建设银行网站注销吗网页制作作品
  • 家具网站建设目的及功能定位网页游戏在哪里制作
  • 高端网站开发步骤网站设计制作如何评价
  • 漳州企业网站建设制作做发型的网站
  • 承包酒席可以做网站吗网站建设小组的运营模式