main函数
main函数所在文件为main/srs_main_server.cpp
中。
该文件定义了一些全局变量:
- _srs_log:全局的log文件
- _srs_context:全局的context文件。是一个SrsThreadContext类,这个类使用map来存放协程指针到id的映射关系。
std::map<srs_thread_t, int> cache;
- _srs_config:全局配置文件
执行流程如图:
run_master
程序进入run_master。在该函数中,服务器做一些初始化工作并调用listern监听客户端的连接,然后调用do_cycle函数(死循环),做一些监控,更新时间及缓存等。
执行流程如图:
代码分析如下:
//run()调用run_master(),启动
srs_error_t run_master(SrsServer* svr)
{
srs_error_t err = srs_success;
//初始化st
if ((err = svr->initialize_st()) != srs_success) {
return srs_error_wrap(err, "initialize st");
}
//初始化signal:创建signal pipe
if ((err = svr->initialize_signal()) != srs_success) {
return srs_error_wrap(err, "initialize signal");
}
//将pid线程写进文件
if ((err = svr->acquire_pid_file()) != srs_success) {
return srs_error_wrap(err, "acquire pid file");
}
//监听客户端请求
if ((err = svr->listen()) != srs_success) {
return srs_error_wrap(err, "listen");
}
//注册信号(开启了新的协程)
if ((err = svr->register_signal()) != srs_success) {
return srs_error_wrap(err, "register signal");
}
//undo
if ((err = svr->http_handle()) != srs_success) {
return srs_error_wrap(err, "http handle");
}
//undo
if ((err = svr->ingest()) != srs_success) {
return srs_error_wrap(err, "ingest");
}
//服务器的循环
if ((err = svr->cycle()) != srs_success) {
return srs_error_wrap(err, "main cycle");
}
return err;
}
do_cycle
srs_error_t SrsServer::do_cycle()
{
srs_error_t err = srs_success;
// find the max loop
int max = srs_max(0, SRS_SYS_TIME_RESOLUTION_MS_TIMES);
#ifdef SRS_AUTO_STAT
max = srs_max(max, SRS_SYS_RUSAGE_RESOLUTION_TIMES);
max = srs_max(max, SRS_SYS_CPU_STAT_RESOLUTION_TIMES);
max = srs_max(max, SRS_SYS_DISK_STAT_RESOLUTION_TIMES);
max = srs_max(max, SRS_SYS_MEMINFO_RESOLUTION_TIMES);
max = srs_max(max, SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES);
max = srs_max(max, SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES);
max = srs_max(max, SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES);
#endif
// for asprocess.
bool asprocess = _srs_config->get_asprocess();
// the deamon thread, update the time cache
while (true) {
//这里handle为NULL
if (handler && (err = handler->on_cycle()) != srs_success) {
return srs_error_wrap(err, "handle callback");
}
// the interval in config. default=9.9
int heartbeat_max_resolution = (int)(_srs_config->get_heartbeat_interval() / SRS_SYS_CYCLE_INTERVAL);
// dynamic fetch the max. 1
int dynamic_max = srs_max(max, heartbeat_max_resolution);
for (int i = 0; i < dynamic_max; i++) {
//主线程休眠,让出CPU,其他线程如conn接受连接
srs_usleep(SRS_SYS_CYCLE_INTERVAL * 1000); //1000 * 1000, 1s
// asprocess check.
if (asprocess && ::getppid() != ppid) {
return srs_error_new(ERROR_ASPROCESS_PPID, "asprocess ppid changed from %d to %d", ppid, ::getppid());
}
// gracefully quit for SIGINT or SIGTERM. 收到腿出信号,返回
if (signal_gracefully_quit) {
srs_trace("cleanup for gracefully terminate.");
return err;
}
// for gperf heap checker,
// @see: research/gperftools/heap-checker/heap_checker.cc
// if user interrupt the program, exit to check mem leak.
// but, if gperf, use reload to ensure main return normally,
// because directly exit will cause core-dump.
#ifdef SRS_AUTO_GPERF_MC
if (signal_gmc_stop) {
srs_warn("gmc got singal to stop server.");
return err;
}
#endif
// do persistence config to file.
if (signal_persistence_config) {
signal_persistence_config = false;
srs_info("get signal to persistence config to file.");
if ((err = _srs_config->persistence()) != srs_success) {
return srs_error_wrap(err, "config persistence to file");
}
srs_trace("persistence config to file success.");
}
// do reload the config. 重新加载配置的信号
if (signal_reload) {
signal_reload = false;
srs_info("get signal to reload the config.");
if ((err = _srs_config->reload()) != srs_success) {
return srs_error_wrap(err, "config reload");
}
srs_trace("reload config success.");
}
// notice the stream sources to cycle. 流资源循环
if ((err = SrsSource::cycle_all()) != srs_success) {
return srs_error_wrap(err, "source cycle");
}
// update the cache time 事件缓存
if ((i % SRS_SYS_TIME_RESOLUTION_MS_TIMES) == 0) {
srs_info("update current time cache.");
srs_update_system_time_ms();
}
#ifdef SRS_AUTO_STAT
if ((i % SRS_SYS_RUSAGE_RESOLUTION_TIMES) == 0) {
srs_info("update resource info, rss.");
srs_update_system_rusage();
}
if ((i % SRS_SYS_CPU_STAT_RESOLUTION_TIMES) == 0) {
srs_info("update cpu info, cpu usage.");
srs_update_proc_stat();
}
if ((i % SRS_SYS_DISK_STAT_RESOLUTION_TIMES) == 0) {
srs_info("update disk info, disk iops.");
srs_update_disk_stat();
}
if ((i % SRS_SYS_MEMINFO_RESOLUTION_TIMES) == 0) {
srs_info("update memory info, usage/free.");
srs_update_meminfo();
}
if ((i % SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES) == 0) {
srs_info("update platform info, uptime/load.");
srs_update_platform_info();
}
if ((i % SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES) == 0) {
srs_info("update network devices info.");
srs_update_network_devices();
}
if ((i % SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES) == 0) {
srs_info("update network server kbps info.");
resample_kbps();
}
if (_srs_config->get_heartbeat_enabled()) {
if ((i % heartbeat_max_resolution) == 0) {
srs_info("do http heartbeat, for internal server to report.");
http_heartbeat->heartbeat();
}
}
#endif
srs_info("server main thread loop");
}
}
return err;
}