openGauss数据库源码解析(三)| 公共组件源码解析(2)

3.2 数据库初始化
数据库正常启动时需要指定数据目录,数据目录中包括了系统表的初始化数据。数据库初始化的过程会生成这些初始系统表数据文件,该过程由initdb和openGauss进程配合生成。initdb控制执行过程,创建目录和基本的配置文件;openGauss进程负责系统表的初始化。initdb通过PG_CMD_OPEN宏启动openGauss进程,同时打开一个管道流,然后通过解析系统表文件中的SQL命令,并把命令通过PG_CMD_PUTS宏的管道流发给openGauss进程,最后通过PG_CMD_CLOSE宏关闭管道流。PG_CMD_OPEN宏是系统函数popen的封装宏,PG_CMD_PUTS宏是系统函数fputs的封装宏,PG_CMD_CLOSE宏是系统函数pclose的封装宏。交互过程如图3-1所示。

图3-1 初始化交互过程图

initdb在创建template1模板数据库时,命令参数指定了“snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1, “”%s" --boot -x1 %s %s", backend_exec, boot_options, talkargs);”,其中“–boot”表示openGauss进程以一个特殊的bootstrap模式运行。在其他初始化系统表时,initdb命令参数指定了“snprintf_s(cmd, sizeof(cmd), sizeof(cmd) - 1, “”%s" %s template1 >%s", backend_exec, backend_options, DEVNULL); ”,其中“static const char* backend_options = "–single "”表示openGauss进程以单用户模式运行。
下面以setup_schema函数为例详细介绍这个过程。相关代码如下:

{ PG_CMD_DECL; char** line; char** lines; int nRet = 0; char* buf_features = NULL; fputs(_("creating information schema ... "), stdout); (void)fflush(stdout); lines = readfile(info_schema_file); /* * 使用-j 避免在information_schema.sql反斜杠处理 */ nRet = snprintf_s( cmd, sizeof(cmd), sizeof(cmd) - 1, ""%s" %s -j template1 >%s", backend_exec, backend_options, DEVNULL); securec_check_ss_c(nRet, "