首页 > 代码库 > squid源码分析之--epoll和event驱动机制
squid源码分析之--epoll和event驱动机制
最近在看squid的源码,刚开始毫无头绪,后来逐步找到一些感觉,记录之。
squid的源码中大概有100多个c文件,一个一个地看明显行不通。我们需要逐步找出设计者的主线。
先从main.c入手,需要关注的,是main.c离结尾比较近的那一段,它是squid的心脏:
“for(;;){
...
event_run();
...
swich(comm_select()...
...
}"
event_run()函数定义在event.c文件里,它每次在恰当的时间从event.c的一个全局的event队列中摘下一个event执行它的回调函数。主函数重复地执行这一句意味着我们只需要找出那些将event加进任务队列里面的时机,即eventAdd()函数的调用者,我们对squid整个运行机制的理解就是封闭的了。
查找eventAdd()的caller(调用者),你会发现这个函数在这些c文件的定义中出现了120多次。
在这些caller中,有一些是纯事件处理,看到底就是一堆回调。
还有一些,是squid的epoll机制在底层驱动着。
你应该已经注意到main.c中的event_run()后面的comm_select()函数,查查它的定义,你会发现它下一层的do_comm_select()中调用了我们熟悉的epoll_wait(),在这
里它已经在等待epoll_event的就绪了,那么这些ev是在什么时候注册进去的呢?
仔细查看comm_epoll.c,你会发现ev只能通过comm_setEvents()中的epoll_ctl()注册到全局的KDPFD(一个epoll描述符),从comm_setEvents一层一层向上找,你会发
现源头出现在mai.c的mainInitialize();这正是我们希望看到的。这之间你可以清楚的看到squid是如何一步一步建立TCP连接的,socket()、bind()、listen()的调用你
都会一一找到。
那么epoll如何和event衔接呢?
在clientHttpConnectionsOpen()中,你会找到一个commSetSelect(...httpAccept...)函数,注意这里的参数,它将httpAccept以回调的方式注册了进去。那么这个回调
何时触发呢?答案是,在epoll_wait()返回之后。具体的步骤可以很容易找出来。这里不再赘述。
httpAccept()->clientdbEstablished()->clientdbAdd()->eventAdd()...到此,我们终于找到了熟悉的eventAdd()。
从初始化,到epoll机制,到连接建立完成,到eventAdd和event_run,我们已经找到了squid的核心驱动的主线。
至于往event队列里加什么内容,那就由上层需求而定了,最熟悉的就是http服务。
搞清楚这些,squid的其他机制就可以很轻松的分析了。甚至可以把自己的一些需求加进去。