版权声明:转载请注明来源 https://blog.csdn.net/u013702678/article/details/81213269
前面几篇我们分析了server的创建过程,这篇我们开始分析server的启动过程,这里的代码在E:\swoole-src-master\src\network\Server.c里面。
int swServer_start(swServer *serv)
{
swFactory *factory = &serv->factory;//获取factory对象
int ret;
//server启动前的有效性检查
ret = swServer_start_check(serv);
if (ret < 0)
{
return SW_ERR;
}
//判断是否设置了server启动前的钩子函数设置,如果设置了则调用钩子函数
if (SwooleG.hooks[SW_GLOBAL_HOOK_BEFORE_SERVER_START])
{
//调用钩子函数
swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_START, serv);
}
//判断服务是否已经启动,这里通过cas操作,如果失败表示当前serv->gs_start不为0
if (!sw_atomic_cmp_set(&serv->gs->start, 0, 1))
{
swoole_error_log(SW_LOG_ERROR, SW_ERROR_SERVER_ONLY_START_ONE, "must only start one server.");
return SW_ERR;
}
//全局日志工具初始化
if (SwooleG.log_file)
{
//日志工具初始化,这里初始化逻辑比较简单,也就是打开日志文件而已。
swLog_init(SwooleG.log_file);
}
//serv以demon方式启动
if (serv->daemonize > 0)
{
if (SwooleG.log_fd > STDOUT_FILENO)//日志文件描述符大于标准输出文件描述符
{
swoole_redirect_stdout(SwooleG.log_fd);//文件描述符的重定向
}
else//日志文件描述符小于标准输出文件描述符
{
SwooleG.null_fd = open("/dev/null", O_WRONLY);//打开/dev/null文件
if (SwooleG.null_fd > 0)
{
swoole_redirect_stdout(SwooleG.null_fd);//将标准输出重定向到/dev/null文件
}
else //打开文件失败
{
swoole_error_log(SW_LOG_ERROR, SW_ERROR_SYSTEM_CALL_FAIL, "open(/dev/null) failed. Error: %s[%d]", strerror(errno), errno);
}
}
//将当前进程变为demon进程,这里是demon进程的标准操作,不再展开分析
if (daemon(0, 1) < 0)
{
return SW_ERR;
}
}
serv->gs->master_pid = getpid();//记录master进程的进程pid
serv->gs->now = serv->stats->start_time = time(NULL);//记录serv的启动时间和当前时间
//如果分发模式为unix域协议
if (serv->dispatch_mode == SW_DISPATCH_STREAM)
{
//创建unix域协议路径,最终生成的域协议路径为/tmp/swoole.%d.sock,其中%d为master进程的进程号
serv->stream_socket = swoole_string_format(64, "/tmp/swoole.%d.sock", serv->gs->master_pid);
if (serv->stream_socket == NULL)//创建失败
{
return SW_ERR;
}
int _reuse_port = SwooleG.reuse_port;//记录全局swooleG变量的reuse_port属性
SwooleG.reuse_port = 0;//设置为0
serv->stream_fd = swSocket_create_server(SW_SOCK_UNIX_STREAM, serv->stream_socket, 0, 2048);//创建socket,这里会完成create,bind,listen等操作,后续再展开分析。
if (serv->stream_fd < 0)//socket描述符,小于0表示创建失败
{
return SW_ERR;
}
//描述符设置O_NONBLOCK和FD_CLOEXEC属性,通过fcntl操作
swoole_fcntl_set_option(serv->stream_fd, 1, 1);
SwooleG.reuse_port = _reuse_port;//回填reuse_port属性,没看懂为什么这里要这么操作
}
serv->send = swServer_tcp_send;//设置serv的send回调函数
serv->sendwait = swServer_tcp_sendwait;//设置serv的sendwait回调函数
serv->sendfile = swServer_tcp_sendfile;//设置serv的sendfile回调函数
serv->close = swServer_tcp_close;//设置serv的close回调函数
//从内存池申请worker对应的空间,这里需要申请worker_num个swWorker对象的大小
serv->workers = SwooleG.memory_pool->alloc(SwooleG.memory_pool, serv->worker_num * sizeof(swWorker));
if (serv->workers == NULL)//空间申请失败
{
swoole_error_log(SW_LOG_ERROR, SW_ERROR_SYSTEM_CALL_FAIL, "gmalloc[server->workers] failed.");
return SW_ERR;
}
serv->gs->event_workers.workers = serv->workers;//设置属性
serv->gs->event_workers.worker_num = serv->worker_num;//worker_num属性
serv->gs->event_workers.use_msgqueue = 0;//是否使用msgqueue的标记
int i;
for (i = 0; i < serv->worker_num; i++)
{
//初始化每个worker进程的swProcessPool属性
serv->gs->event_workers.workers[i].pool = &serv->gs->event_workers;
}
#ifdef SW_USE_RINGBUFFER
for (i = 0; i < serv->reactor_num; i++)
{
//申请每个reactor线程的buffer空间
serv->reactor_threads[i].buffer_input = swRingBuffer_new(SwooleG.serv->buffer_input_size, 1);
if (!serv->reactor_threads[i].buffer_input)//申请空间失败
{
return SW_ERR;
}
}
#endif
//work进程里面有task线程,则初始化task线程的属性
if (serv->task_worker_num > 0 && serv->worker_num > 0)
{
serv->task_result = sw_shm_calloc(serv->worker_num, sizeof(swEventData));
serv->task_notify = sw_calloc(serv->worker_num, sizeof(swPipe));
for (i = 0; i < serv->worker_num; i++)
{
//task线程管道初始化
if (swPipeNotify_auto(&serv->task_notify[i], 1, 0))
{
return SW_ERR;
}
}
}
//用户侧的worker进程列表有设置
if (serv->user_worker_list)
{
swUserWorker_node *user_worker;
i = 0;
LL_FOREACH(serv->user_worker_list, user_worker)
{
//设置worker进程的worker->id属性
user_worker->worker->id = serv->worker_num + serv->task_worker_num + i;
i++;
}
}
//启动factory对象,这里不同factory的启动不一样,后面专篇分析
if (factory->start(factory) < 0)
{
return SW_ERR;
}
//server对应的信号的初始化
swServer_signal_init(serv);
//记录进程ID,这里记录的是master进程的进程ID
if (serv->pid_file)
{
ret = snprintf(SwooleTG.buffer_stack->str, SwooleTG.buffer_stack->size, "%d", getpid());
swoole_file_put_contents(serv->pid_file, SwooleTG.buffer_stack->str, ret);
}
if (serv->factory_mode == SW_MODE_SINGLE)//如果是单进程的模式,也就是reactor和worker是同类角色
{
//Reactor的启动
ret = swReactorProcess_start(serv);
}
else //其他模式
{
//Reactor的启动
ret = swServer_start_proxy(serv);
}
swServer_free(serv);//释放serv的空间,前面的启动后都是在不同的进程中
serv->gs->start = 0;//标记start标记为0
//删除master进程的进程文件
if (serv->pid_file)
{
unlink(serv->pid_file);
}
return SW_OK;
}