概述
本文接上文,继续分析和探讨beanstalk的实现原理。本文对beanstalk的启动过程做一个分析,这样可以对其运行框架有一个总体上的把握。
beanstalkd是使用epoll作为事件处理框架,为什么epoll如此高效,可以参考我以前写的一篇对其实现代码分析的文章。
源码分析
软件入口
beanstalkd的初始化流程代码非常简洁。主要完成各种数据结构的初始化,创建服务器监听socket,然后启动epoll的事件驱动模型,监听客户端连接请求。
int
main(int argc, char **argv)
{
int r;
struct job list = {}; //job空头节点
progname = argv[0];
setlinebuf(stdout);
optparse(&srv, argv+1); //分解启动参数
if (verbose) {
printf("pid %d\n", getpid());
}
r = make_server_socket(srv.addr, srv.port); //创建服务器监听socket fd
if (r == -1) twarnx("make_server_socket()"), exit(111);
srv.sock.fd = r;
prot_init();
if (srv.user) su(srv.user); //转换成srv.user用户来运行
set_sig_handlers(); // 安装信号处理函数
if (srv.wal.use) {
// We want to make sure that only one beanstalkd tries
// to use the wal directory at a time. So acquire a lock
// now and never release it.
if (!waldirlock(&srv.wal)) {
twarnx("failed to lock wal dir %s", srv.wal.dir);
exit(10);
}
// 初始化job链表头
list.prev = list.next = &list;
walinit(&srv.wal, &list);
r = prot_replay(&srv, &list);
if (!r) {
twarnx("failed to replay log");
return 1;
}
}
// 启动服务器事件监听
srvserve(&srv);
return 0;
}
初始化服务
这一步会完成一个服务器的基本框架。大多数的后台服务这一段代码都相似。
这里是通过epoll的方式来实现事件处理框架。其实很多软件都是用epoll。
// 服务器监听初始化过程
void srvserve(Server *s)
{
int r;
Socket *sock;
int64 period;
if (sockinit() == -1) { //socket初始化,其实就是调用epoll_create得到一个fd。
twarnx("sockinit");
exit(1);
}
s->sock.x = s; // 这里Socket结构中的x字段保存的是Server结构的指针
s->sock.f = (Handle)srvaccept; // 当有连接请求到来时,调用Socket结构中的f回调函数
s->conns.less = (Less)connless; //
s->conns.rec = (Record)connrec; //
r = listen(s->sock.fd, 1024); // 创建服务器监听socket
if (r == -1) {
twarn("listen");
return;
}
r = sockwant(&s->sock, 'r'); // 为s->sock.fd添加读事件到epoll_ctl中,用来相应客户端的连接请求
if (r == -1) {
twarn("sockwant");
exit(2);
}
for (;;) { // 进入死循环进行事件处理
period = prottick(s); // 处理超时的job
int rw = socknext(&sock, period); // 某个fd有读或写事件发生
if (rw == -1) {
twarnx("socknext");
exit(1);
}
if (rw) { // 调用对应的函数处理该事件
sock->f(sock->x, rw); //第一次是调用srvaccept函数来接受客户端的连接请求
}
}
}
总结
本文描述了beanstalk的启动过程,并对其启动代码进行了一些分析。通过本文,可以对beanstalk的启动过程和处理框架有一个比较清楚的认识了。