Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1780841
  • 博文数量: 413
  • 博客积分: 8399
  • 博客等级: 中将
  • 技术积分: 4325
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-09 10:44
文章分类

全部博文(413)

文章存档

2015年(1)

2014年(18)

2013年(39)

2012年(163)

2011年(192)

分类: C/C++

2011-06-09 11:55:03

     无意之间将08年做的一个用到memcached项目翻了出来,于是就开始了对memcached实现源代码的阅读。我将陆续发布一些关于memcached源代码分析的blog. 因为memcached的实现用到了libevent库,所以从libevent开始。

下面的代码摘录改写自memcached-1.2.8源代码memcached.c中.
演示使用libevent(~provos/libevent/)中的Timer的功能输出当前距离Epoch的秒数:

  1. #include <stdio.h>
  2. #include <event.h>
  3. #include <sys/time.h>
  4. #include <unistd.h>
  5. #include <stdbool.h>
  6. #include <stdint.h>
  7. #include <fcntl.h>
  8. #include <stdlib.h>
  9. #define rel_time_t unsigned int

  10. static struct event clockevent;
  11. static struct event_base *main_base;
  12. volatile rel_time_t current_time;

  13. static void set_current_time(void)
  14. {
  15.         struct timeval timer;
  16.         gettimeofday(&timer, NULL);
  17.         current_time = (rel_time_t) (timer.tv_sec);
  18. }
  19. static void clock_handler(const int fd, const short which, void *arg)
  20. {
  21.         struct timeval t = {.tv_sec = 1, .tv_usec = 0 };
  22.         static bool initialized = false;
  23.         if(initialized){
  24.                 evtimer_del(&clockevent);
  25.         }else{
  26.                 initialized = true;
  27.         }
  28.         evtimer_set(&clockevent, clock_handler, 0);
  29.         event_base_set(main_base, &clockevent);
  30.         evtimer_add(&clockevent, &t);
  31.         set_current_time();
  32.         printf("current_time: %d\n", current_time);
  33. }
  34. int main()
  35. {
  36.         main_base = event_init();
  37.         clock_handler(0, 0, 0);
  38.         event_base_loop(main_base, 0);

  39.         return 0;
  40. }
编译:
gcc -Wall -levent testTime.c -o testTime // 注意这里加入连接选项 -levent
执行:
./testTime
结果:
current_time: 1307674213
current_time: 1307674214
current_time: 1307674215
current_time: 1307674216
current_time: 1307674217
current_time: 1307674218
current_time: 1307674219
current_time: 1307674220
current_time: 1307674221
current_time: 1307674222
current_time: 1307674223
current_time: 1307674224
current_time: 1307674225
current_time: 1307674226
^C

对libevent中Timer的分析:
(~provos/libevent/doxygen-2.0.1/)
Timer:
libevent can also be used to create timers that invoke a callback after a certain amount of time has expired. The function prepares an event struct to be used as a timer. To activate the timer, call . Timers can be deactivated by calling .

大意思是:
libevent也能被用作一个“定时触发器”,当指定的时间到期时,能够回调指定的特定函数(比如上面的代码是回调event_handler,也就是说event_handler每个1秒就再回调一次自己)。evtimer_set()函数初始化一个timer,激活timer调用evtimer_add()函数,删除timer调用evtimer_del()函数。

1.evtimer_set()函数原型:
void evtimer_set(struct event ev, void(*)(evutil_socket_t, short, void *) cb, void *arg)
该函数修改结构体ev,将回调函数cb,回调函数的参数arg赋值该结构体ev中的成员。

也许看到这里你会有一个疑问:
在上面的代码中,在main中我们调用clock_handler(0, 0, 0), 可以知道clock_handler有三个参数,但是在clock_handler中的:evtimer_set(&clockevent, clock_handler, 0); 在将clock_handler设置为回调函数时,却只是给出了一个参数0, 这里如何解释呢?
这是因为:
#define evtime_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg)
也就是说evtimer_set(&clockevent, clock_handler, 0)中隐藏了-1, 0两个参数,所以真正参给回调函数应该是三个参数:clock_handler(-1,0,0)。符合clock_handler的原型。有点像C++中默认参数的功能。

2.event_base_set函数原型:
int event_base_set(struct event_base *eb, struct event *ev)
Associate a different event base with an event.
将一个event关联到一个不同的event base. 也就说我们可以将一个event关联到不同的event base.

3.evtimer_add函数原型:
int evtimer_add(struct event *ev, const struct timeval *timeout)
Add an event to the set of monitored events. 将一个event加入到被监视的事件集合。
ev an event struct initialized via
timeout the maximum amount of time to wait for the event, or NULL to wait forever.

4.evtimer_del函数原型:
#define evtimer_del(ev)  event_del(ev)
so:
int evtimer_del(struct event * ev)
Delete a timer event.
ev the event struct to be disabled

 














main 执行的流程为:
event_handler()第一次执行,将event_handler自己设为回调函数,在event_handler()第一次执行完成之后退出,1秒中之后,main_base又会触发event_handler再执行一次,第二次以及之后event_handler的执行,是先将上一次的event struct删除,然后初始化再重新加入,这样就周而复始,就实现了每隔1秒钟set_current_time()函数和print函数就执行一次从而输出时间。

总结一下:
1. 首先调用event_base_new(或者event_init,推荐调用前者),对libevent进行唯一的一次初始化。
before using any of the functions in the library, you must call or  to perform one-time initialization of the libevent library.

2. 然后调用evtimer_set初始化一个struct event结构体,也就是将利用evtimer_set的参数(即回调函数和回调函数的参数)填充struct event 结构体。
The function prepares an event struct to be used as a timer。

再调用evtimer_add()将被evtimer_set初始化的struct event结构体加入到被监视的集合中.
To activate the timer, call .

删除一个event调用evtimer_del()
Timers can be deactivated by calling .

3.最后调用event_base_loop()或者event_base_dispatch()或者event_dispatch(),推荐调用第一个,最后一个是非线程安全的版本。
从而开始处理事件集合,开始对event集合进行监视monitor.
Loop to process events. In order to process events, an application needs to call . event_base_dispatch() is threadsafe event dispatching loop.
event_base_loop() is a more flexible version of .

注意带有base字样的函数是对全局的libevent进行操作的。

阅读(16013) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:Ubuntu中利用配置PPPoE上网

给主人留下些什么吧!~~