1.下载地址http://www.viewtier.com/downloads.htm2.sh -y ./paraxxxxxx.shparabuild配置备忘安装位置是/opt/parabuild链接位置是/usr/bin启动命令/etc/init.d/parabuild start永久授权licenseproduct=Vie
一、libevent的使用
首先我们知道,memcached是使用了iblievet作为网络框架的,而iblievet又是单线程模型的基于linux下epoll事件的异步模型。因此,其基本的思想就是 对可读,可写,超时,出错等事件进行绑定函数,等有其事件发生,对其绑定函数回调。
可以减掉了解一下 libevent基本api调用
[cpp] view
plain copy

-
struct event_base *base;
-
base = event_base_new();
event_base_new对比epoll,可以理解为epoll里的epoll_create。
event_base内部有一个循环,循环阻塞在epoll调用上,当有一个事件发生的时候,才会去处理这个事件。其中,这个事件是被绑定在event_base上面的,每一个事件就会对应一个struct event,可以是监听的fd。
其中struct event 使用event_new 来创建和绑定,使用event_add来启用,例如:
[cpp] view
plain copy

-
struct event *listener_event;
-
listener_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (void*)base);
参数说明:
base:event_base类型,event_base_new的返回值
listener:监听的fd,listen的fd
EV_READ|EV_PERSIST:事件的类型及属性
do_accept:绑定的回调函数
(void*)base:给回调函数的参数
event_add(listener_event, NULL);
对比epoll:
event_new相当于epoll中的epoll_wait,其中的epoll里的while循环,在libevent里使用event_base_dispatch。
event_add相当于epoll中的epoll_ctl,参数是EPOLL_CTL_ADD,添加事件。
注:libevent支持的事件及属性包括(使用bitfield实现,所以要用 | 来让它们合体)
EV_TIMEOUT: 超时
EV_READ: 只要网络缓冲中还有数据,回调函数就会被触发
EV_WRITE: 只要塞给网络缓冲的数据被写完,回调函数就会被触发
EV_SIGNAL: POSIX信号量
EV_PERSIST: 不指定这个属性的话,回调函数被触发后事件会被删除
EV_ET: Edge-Trigger边缘触发,相当于EPOLL的ET模式
事件创建添加之后,就可以处理发生的事件了,相当于epoll里的epoll_wait,在libevent里使用event_base_dispatch启动event_base循环,直到不再有需要关注的事件。
有了上面的分析,结合之前做的epoll服务端程序,对于一个服务器程序,流程基本是这样的:
1. 创建socket,bind,listen,设置为非阻塞模式
2. 创建一个event_base,即
[cpp] view
plaincopy
-
struct event_base * event_base_new(void)
3. 创建一个event,将该socket托管给event_base,指定要监听的事件类型,并绑定上相应的回调函数(及需要给它的参数)。即
[cpp] view
plaincopy
-
struct event * event_new(struct event_base *base, evutil_socket_t fd, short events, void (*cb)(evutil_socket_t, short, void *), void *arg)
4. 启用该事件,即
[cpp] view
plaincopy
-
int event_add(struct event *ev, const struct timeval *tv)
5. 进入事件循环,即
[cpp] view
plaincopy
-
int event_base_dispatch(struct event_base *event_base)
有了上边的基础东西,可以进入memcached的阅读了。
二、memcached源码分析
main函数启动,首先会初始化很多数据,这里我们只涉及大网络这块,其他以后分析,先忽略。
1.首先初始化 主工作线程的的iblievet对象
[cpp] view
plain copy

-
-
main_base = event_init();
最后会调用
[cpp] view
plain copy

-
-
if (event_base_loop(main_base, 0) != 0) {
-
retval = EXIT_FAILURE;
-
}
在该对象内部循环。不退出。
2.初始化连接的对象
[cpp] view
plain copy

-
static void conn_init(void) {
-
freetotal = 200;
-
freecurr = 0;
-
if ((freeconns = calloc(freetotal, sizeof(conn *))) == NULL) {
-
fprintf(stderr, "Failed to allocate connection structures\n");
-
}
-
return;
-
}
这里是先预先分配200个conn*的内存。等有连接上来,会从
freeconns 取。
如下代码:
Copyright ©
版权所有 本站资源均来自互联网或会员发布,如果侵犯了您的权益请与我们联系,我们将在24小时内删除!谢谢!