SRS4.0源代码分析之启动流程

目标:

通过分析代码的启动流程,可以了解各功能模块的启动顺序,以及模块间的调用、依赖关系。为后续的学习、分析达到一种庖丁解牛的效果。

内容:

SRS服务器的入口函数(mian函数)在srs_main_server.cpp文件里,下面的代码为了方便理解,只列出了函数中关键的处理过程。

int main(int argc, char** argv) {
    srs_error_t err = do_main(argc, argv); // srs_error_t是一个包含错误信息的对象指针
    srs_freep(err); // 释放错误对象
}

srs_error_t do_main(int argc, char** argv)
{
    srs_thread_initialize();  // 此函数内部创建_srs_log、_srs_context、_srs_config全局对象
                              // 并调用StateThreads库的初始化函数,创建Idle协程(负责epoll和轮询定时器)
                              // 创建全局管理对象SrsHybridServer、SrsLiveSourceManager、SrsRtcSourceManager、SrsResourceManager
    _srs_context->set_id(_srs_context->generate_id());  // 生成一个随机字符串,
                                                        // 并关联到当前原始协程

    _srs_config->parse_options(argc, argv); // 读取配置文件
    
    SrsFileLog::initialize();  // 根据配置文件,初始化日志模块的输出方向(文件或控制台)和输出级别
    
    run_directly_or_daemon(); // 此函数内部判断是否需要以后台模式运行,并启动全部服务
}

函数run_directly_or_daemon(),首先判断配置文件的设置,如果是后台运行模式,则通过连续调用fork启动孙进程,同时子进程退出,孙进程变为孤儿进程,因为Linux系统会让init进程接管孤儿进程,当孤儿进程结束时init进程会自动发现并清理,最终,防止出现僵尸进程。

srs_error_t run_directly_or_daemon() {
    ......  // 根据配置文件的设置,如果需要后台运行,则通过连续调用fork进入孙进程
            // 子进程创建完孙子进程后就退出,则孙进程直接变为一个孤儿进程,
            // Linux系统处理孤儿进程的方式是让init进程接管孤儿进程,而init进程会自动发现并清理属于自己的僵尸进程
    run_hybrid_server(); // 启动服务
}

接下来,在run_hybrid_server()函数中注册各种流媒体服务对象

srs_error_t run_hybrid_server()
{
    // _srs_hybrid指向一个全局SrsHybridServer对象
    // 实际工作对象SrsServerAdapter和RtcServerAdapter被注入到SrsHybridServer对象内部
    _srs_hybrid->register_server(new SrsServerAdapter()); // 创建并注册RTMP服务
#ifdef SRS_SRT
    _srs_hybrid->register_server(new SrtServerAdapter()); // 创建并注册SRT服务
#endif
    _srs_hybrid->register_server(new RtcServerAdapter()); // 创建并注册WebRTC服务
    
    _srs_hybrid->initialize();  // 此函数内部分别启动几个周期定时器,并以遍历方式调用上面已注册服务器的initialize()函数
    
    _srs_circuit_breaker->initialize();  // 此模块用于防止服务器过载,实现过载保护
    
    _srs_hybrid->run();  // 此函数内部以遍历方式调用上面已注册服务器的run接口,并在最后
                         // 调用srs_usleep(SRS_UTIME_NO_TIMEOUT)使当前的原始协程进入休眠状态

    _srs_hybrid->stop(); // 如果执行到这里,表示整个服务已结束,程序即将退出
}

本文福利, C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部↓↓

 

最终,通过SrsHybridServer::run()函数启动各个流媒体服务模块,并通过srs_usleep()函数阻塞当前的原始协程

srs_error_t SrsHybridServer::run()
{
    srs_error_t err = srs_success;

    vector<ISrsHybridServer*>::iterator it;
    for (it = servers.begin(); it != servers.end(); ++it) {
        ISrsHybridServer* server = *it;
        // 遍历调用已注册服务器模块的run()接口,将各种服务模块运行起来
        if ((err = server->run()) != srs_success) {
            return srs_error_wrap(err, "run server");
        }
    }

    // Wait for all server to quit.
    srs_usleep(SRS_UTIME_NO_TIMEOUT); // 最终,原始协程阻塞在这里,整个服务器启动完成

    return err;
}

总结:

1、通过学习SRS的启动流程,我们对SRS有了进一步的认识,如果对其中state-threads库感兴趣,可以从srs_thread_initialize()函数内部开始深入分析;如果对配置文件的处理比较感兴趣,可以从SrsConfig::parse_options()函数内部开始分析;如果对服务器的后台启动方式感兴趣,可以关注run_directly_or_daemon()函数。

2、最终,我们可以很自然的看到SRS4.0包括3个主要的服务模块:SrsServerAdapter、SrtServerAdapter、RtcServerAdapter。我们可以根据需要对每个服务模块分别研究。

原文链接:SRS4.0源代码分析之启动流程 - 资料 - 我爱音视频网 - 构建全国最权威的音视频技术交流分享论坛

本文福利, C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部↓↓

猜你喜欢

转载自blog.csdn.net/m0_60259116/article/details/125897689