SRS代码目录
代码目录:
src/目录下核心代码:
- core:核心功能模块,包括日志、配置、错误处理等;
- protocol:实现RTMP、HTTP-FLV、HLS等协议的模块;
- app:应用层的实现,包括流的发布、播放、转码等功能;
- kernel:底层实现,包括网络I/O、多线程处理等;
- main:主层序入口
SRS启动:
main:
// src/main/srs_main_server.cpp
main()
{
do_main();
}
do_main()
{
// 初始化,new创建各种server和实例
srs_global_initialize();
// 启动线程池?
SrsThreadPool::setup_thread_locals();
// 加载conf配置
_srs_config->parse_options(argc, argv);
// 运行主程序
run_directly_or_daemon();
}
srs_global_initialize: 初始化各种server
// src/app/srs_app_threads.cpp
srs_global_initialize()
{
...
// 全局变量 _srs_hybrid:
// SrsHybridServer* _srs_hybrid = NULL;
_srs_hybrid = new SrsHybridServer();
...
}
run_directly_or_daemon: 开始运行
run_directly_or_daemon()
{
// 我们没有配置为daemon
...
int pid = fork();
if (pid > 0) {
// 父进程直接退出
exit(0);
}
// 继续第二次fork()
pid = fork();
if (pid > 0) {
// 父进程退出
exit(0);
}
// 在子进程中开启执行
run_in_thread_pool();
}
run_in_thread_pool
run_in_thread_pool()
{
// 初始化线程池
_srs_thread_pool->initialize();
// 创建run_hybrid_server 工作线程,用于RTMP、RTC server
_srs_thread_pool->execute("hybrid", run_hybrid_server, (void*)NULL)
// 循环执行线程池中的每个线程:
_srs_thread_pool->run();
}
SRS中的线程:
SrsThreadPool 线程池类:
// src/app/srs_app_threads.hpp
class SrsThreadPool {
//
std::vector<SrsThreadEntry*> threads_;
//
std::vector<SrsThreadEntry*> hybrids_;
};
// 线程池构造函数中,先指定主线程(primordial thread)
// primordial thread并不是调用pthread_create()单独创建的,而是指向了当前调用线程
SrsThreadPool::SrsThreadPool() {
entry_ = NULL;
lock_ = new SrsThreadMutex();
hybrid_ = NULL;
// Add primordial thread, current thread itself.
SrsThreadEntry* entry = new SrsThreadEntry();
threads_.push_back(entry); // 插入到线程池中
entry_ = entry;
entry->pool = this;
entry->label = "primordial";
entry->start = NULL;
entry->arg = NULL;
entry->num = 1;
entry->trd = pthread_self(); // 获取当前线程的tid
entry->tid = gettid();
char buf[256];
snprintf(buf, sizeof(buf), "srs-master-%d", entry->num);
entry->name = buf;
pid_fd = -1;
}
SrsThreadEntry 线程类:
// src/app/srs_app_threads.hpp
class SrsThreadEntry {
SrsThreadPool* pool; // 此线程所在的线程池
pid_t tid;
pthread_t trd;
string name;
srs_error_t (*start)(void* arg); // 线程入口函数
void* arg; // 线程入参
};
_srs_thread_pool是一个全局变量,启动时初始化:
SrsThreadPool* _srs_thread_pool = new SrsThreadPool();
SRS中的Server:
hybrid_server:
// 虚基类,为不同的server子类提供接口
// The hyrid server interfaces, we could register many servers.
class ISrsHybridServer {
public:
ISrsHybridServer();
virtual ~ISrsHybridServer();
public:
virtual srs_error_t initialize() = 0;
virtual srs_error_t run(SrsWaitGroup* wg) = 0;
virtual void stop() = 0;
};
// 管理hybrid server的类
// The hybrid server manager.
class SrsHybridServer : public ISrsFastTimer {
private:
std::vector<ISrsHybridServer*> servers; // 管理所有hybrid server
SrsFastTimer* timer20ms_;
...
virtual void register_server(ISrsHybridServer* svr);
};
SRS中hybrid server类型:
// The SRS server adapter, the master server.
class SrsServerAdapter : public ISrsHybridServer;
// The RTC server adapter.
class RtcServerAdapter : public ISrsHybridServer;
// The srt server adapter, the master server.
class SrsSrtServerAdapter : public ISrsHybridServer;
正如其类名中的“Adapter”所示,这些类是适配类,核心类型是其中真正的server,如SrsServerAdapter中的SrsServer成员、RtcServerAdapter中的SrsRtcServer成员。
SrsServer:
class SrsServerAdapter : public ISrsHybridServer {
private:
SrsServer* srs;
public:
SrsServerAdapter(); // new创建SrsServer
virtual ~SrsServerAdapter();
public:
virtual srs_error_t initialize();
// 调用SrsServer中的initialize等函数完成初始化,并调用SrsServer->start()
virtual srs_error_t run(SrsWaitGroup* wg);
virtual void stop();
public:
virtual SrsServer* instance();
};
SrsServerAdapter::SrsServerAdapter()
{
srs = new SrsServer();
}
SrsServer:
class SrsServer : public ISrsReloadHandler, public ISrsLiveSourceHandler, public ISrsTcpHandler
, public ISrsResourceManager, public ISrsCoroutineHandler, public ISrsHourGlass
{
private:
SrsHttpServer* http_server; // SrsServer中包含一个HttpServer
SrsTcpListener* api_listener_;
SrsTcpListener* http_listener_;
SrsTcpListener* webrtc_listener_;
...
};
SrsRtcServer:
class RtcServerAdapter : public ISrsHybridServer {
private:
SrsRtcServer* rtc;
};
gdb:
使用 GDB 调试程序并传递命令行参数:
gdb --args ./objs/srs -c conf/srs.conf
禁用 LeakSanitizer(设置环境变量):
export LSAN_OPTIONS=detect_leaks=0
gdb与fork:
当程序中调用for()创建子进程时,gdb默认只会继续调试父进程,而会“分离”或忽略子进程。
这是因为gdb通常只调试一个进程。
如果需要控制gdb调试指定父进程或子进程,需要通过特定的调试设置来改变这一行为:
(gdb) set follow-fork-mode child # 调试子进程
(gdb) set follow-fork-mode parent # 调试父进程
查看当前follow-fork-mode的值:
(gdb) show follow-fork-mode
常用gdb命令:
c:continue,跳到下一个断点
n:next,调到下一个函数(不进入函数内部)
s:step,进入函数内部
finish:完成函数
r:从头开始
info threads: 查看当前有多少个线程
info inferiors: 查看当前有多少个进程