【鸿蒙南向】移植案例与原理 - startup子系统之bootstrap_lite部件 (2)

2.3 OHOS_SystemInit函数

函数OHOS_SystemInit()定义在文件base\startup\bootstrap_lite\services\source\system_init.c,代码如下。调用宏函数MODULE_INIT、SYS_INIT和函数SAMGR_Bootstrap()进行初始化启动。

void OHOS_SystemInit(void)
{
    MODULE_INIT(bsp);
    MODULE_INIT(device);
    MODULE_INIT(core);
    SYS_INIT(service);
    SYS_INIT(feature);
    MODULE_INIT(run);
    SAMGR_Bootstrap();
}

我们详细分析下宏函数MODULE_INIT和SYS_INIT的源代码,这2个宏函数在文件base\startup\bootstrap_lite\services\source\core_main.h中定义,代码如下。这些宏函数的参数大都为name和step,name取值为bsp、device、core、service、feature、run,step取值为0。从⑺和⑻处可以看出,分别调用SYS_CALL、MODULE_CALL两个宏,第二个参数设置为0。⑸处定义的MODULE_BEGIN函数,用于返回链接脚本中定义的代码段的开始地址,当传入参数为bsp时,返回&__zinitcall_bsp_start,MODULE_BEGIN函数被展开为如下片段:

{        extern InitCall __zinitcall_sys_start;      \
        InitCall *initCall = &__zinitcall_bsp_start; \
        (initCall);                                      \
}  

⑹处定义的MODULE_END函数,用于返回链接脚本中定义的代码段的结束地址,当传入参数为bsp时,返回&__zinitcall_bsp_end,MODULE_END函数被展开为如下片段:

{        extern InitCall __zinitcall_bsp_end;      \
        InitCall *initCall = &__zinitcall_bsp_end; \
        (initCall);                                    \
}    

⑶和⑷处定义的SYS_BEGIN、SYS_END代码类似,分于返回链接脚本中定义的标记系统服务或特性的代码段的开始、结束地址,即&__zinitcall_sys_service_start、&__zinitcall_sys_service_end、&__zinitcall_sys_feature_start、&__zinitcall_sys_feature_end。⑴处定义的SYS_CALL函数,分别获取链接脚本中zInit代码段的开始initcall和结束地址initend,这些地址存放的是初始化函数的地址,语句 (*initcall)()会循环调用执行这些初始化函数。⑵处MODULE_CALL宏类似。

⑴  #define SYS_CALL(name, step)                                      \
        do {                                                          \
            InitCall *initcall = (InitCall *)(SYS_BEGIN(name, step)); \
            InitCall *initend = (InitCall *)(SYS_END(name, step));    \
            for (; initcall < initend; init
<think>我们注意到在命令中使用了 `--`分隔符,然后传递`--bootstrap`等参数,但是报错 `--bootstrap:not found`。这个错误通常是因为容器入口点(entrypoint)没有正确传递参数导致的。MySQL Router的官方Docker镜像的入口点脚本可能期望在`--`之后传递的参数是`mysqlrouter`命令的参数,但是入口点脚本可能没有正确解析。实际上,根据MySQL RouterDocker镜像的文档和入口点脚本,通常建议将参数直接传递给`mysqlrouter`命令,而不使用`--`分隔符,或者使用`mysqlrouter`作为命令。我们尝试两种方法:方法1:去掉`--`分隔符,将参数直接传递给容器(因为入口点脚本可能设计为直接接受这些参数)方法2:显式地使用`mysqlrouter`命令,然后在后面跟参数。我们首先使用方法1,因为官方文档示例中通常没有使用`--`分隔符。但是,之前使用没有`--`分隔符的命令报错`exec: usage`,所以现在尝试方法2:在镜像名称后显式指定`mysqlrouter`命令,然后传递参数。命令结构如下:docker run[OPTIONS]IMAGE[COMMAND][ARG...]所以,我们将`mysqlrouter`作为COMMAND,后面的参数作为ARG。修改后的命令:</think>### 解决 "exec: --bootstrap: not found" 错误 您遇到的错误 `line 100: exec: --bootstrap: not found` 是由于 Docker 容器入口点(entrypoint)未能正确处理参数传递导致的。以下是完整的解决方案: #### 问题分析: 1. MySQL Router 的官方 Docker 镜像使用 `/entrypoint.sh` 作为入口点 2. 该入口点脚本期望直接接收 `mysqlrouter` 命令,而不是以 `--` 开头的参数 3. 脚本无法识别 `--bootstrap` 作为有效命令 4. 错误发生在容器启动时对参数的解析过程中 #### 解决方案: ##### 1. 显式调用 `mysqlrouter` 命令(推荐) ```bash docker run --name mysql-router \ --network mysql-net \ -v /use01/docker/mysqlrouter:/etc/mysqlrouter \ mysql/mysql-router:8.0.32 \ mysqlrouter \ --bootstrap mgr_user@mysql-master:3306 \ --conf-set-option=DEFAULT.name=router \ --conf-set-option=metadata_cache:Cluster01.bootstrap_server_addresses=mysql-master:3306,mysql-slave1:3306,mysql-slave2:3306 \ --conf-set-option=routing:read_write.bind_port=6446 \ --conf-set-option=routing:read_only.bind_port=6447 \ --conf-set-option=routing:read_write_split.bind_port=6450 \ --force ``` **关键修改:** - 在镜像名称后添加 `mysqlrouter` 命令 - 直接传递所有参数给 `mysqlrouter` 可执行文件 ##### 2. 使用 Dockerfile 自定义入口点 ```dockerfile # Dockerfile.mysqlrouter FROM mysql/mysql-router:8.0.32 # 覆盖原始入口点 ENTRYPOINT ["mysqlrouter"] ``` 构建并运行: ```bash docker build -t custom-mysql-router -f Dockerfile.mysqlrouter . docker run --name mysql-router \ --network mysql-net \ -v /use01/docker/mysqlrouter:/etc/mysqlrouter \ custom-mysql-router \ --bootstrap mgr_user@mysql-master:3306 \ --conf-set-option=DEFAULT.name=router \ --conf-set-option=metadata_cache:Cluster01.bootstrap_server_addresses=mysql-master:3306,mysql-slave1:3306,mysql-slave2:3306 \ --conf-set-option=routing:read_write.bind_port=6446 \ --conf-set-option=routing:read_only.bind_port=6447 \ --conf-set-option=routing:read_write_split.bind_port=6450 \ --force ``` ##### 3. 分步引导和运行(最佳实践) ```bash # 步骤1:引导配置(临时容器) docker run --rm \ --network mysql-net \ -v /use01/docker/mysqlrouter:/etc/mysqlrouter \ mysql/mysql-router:8.0.32 \ mysqlrouter \ --bootstrap mgr_user@mysql-master:3306 \ --conf-set-option=DEFAULT.name=router \ --conf-set-option=metadata_cache:Cluster01.bootstrap_server_addresses=mysql-master:3306,mysql-slave1:3306,mysql-slave2:3306 \ --conf-set-option=routing:read_write.bind_port=6446 \ --conf-set-option=routing:read_only.bind_port=6447 \ --conf-set-option=routing:read_write_split.bind_port=6450 \ --force # 步骤2:运行持久容器 docker run -d --name mysql-router \ --network mysql-net \ -v /use01/docker/mysqlrouter:/etc/mysqlrouter \ -p 6446:6446 -p 6447:6447 -p 6450:6450 \ mysql/mysql-router:8.0.32 ``` #### 自动修复脚本 ```bash #!/bin/bash # run_mysql_router.sh # 引导配置 echo "Bootstrapping MySQL Router configuration..." docker run --rm \ --network mysql-net \ -v /use01/docker/mysqlrouter:/etc/mysqlrouter \ mysql/mysql-router:8.0.32 \ mysqlrouter \ --bootstrap mgr_user@mysql-master:3306 \ --conf-set-option=DEFAULT.name=router \ --conf-set-option=metadata_cache:Cluster01.bootstrap_server_addresses=mysql-master:3306,mysql-slave1:3306,mysql-slave2:3306 \ --conf-set-option=routing:read_write.bind_port=6446 \ --conf-set-option=routing:read_only.bind_port=6447 \ --conf-set-option=routing:read_write_split.bind_port=6450 \ --force # 检查配置文件 if [ ! -f "/use01/docker/mysqlrouter/mysqlrouter.conf" ]; then echo "Error: Configuration file not generated!" exit 1 fi # 运行持久容器 echo "Starting MySQL Router container..." docker run -d --name mysql-router \ --network mysql-net \ -v /use01/docker/mysqlrouter:/etc/mysqlrouter \ -p 6446:6446 -p 6447:6447 -p 6450:6450 \ mysql/mysql-router:8.0.32 # 验证状态 echo "Checking Router status (waiting 15 seconds for startup)..." sleep 15 docker exec mysql-router mysqlrouter --config /etc/mysqlrouter/mysqlrouter.conf status ``` 使用方式: ```bash chmod +x run_mysql_router.sh ./run_mysql_router.sh ``` #### 使用 Docker Compose 解决方案 ```yaml version: '3.8' services: mysql-router: image: mysql/mysql-router:8.0.32 container_name: mysql-router command: - "mysqlrouter" - "--bootstrap" - "mgr_user@mysql-master:3306" - "--conf-set-option=DEFAULT.name=router" - "--conf-set-option=metadata_cache:Cluster01.bootstrap_server_addresses=mysql-master:3306,mysql-slave1:3306,mysql-slave2:3306" - "--conf-set-option=routing:read_write.bind_port=6446" - "--conf-set-option=routing:read_only.bind_port=6447" - "--conf-set-option=routing:read_write_split.bind_port=6450" - "--force" networks: - mysql-net volumes: - /use01/docker/mysqlrouter:/etc/mysqlrouter ports: - "6446:6446" - "6447:6447" - "6450:6450" restart: unless-stopped networks: mysql-net: external: true ``` 运行: ```bash docker-compose up -d ``` #### 高级调试技巧 ##### 1. 检查入口点脚本 ```bash # 查看镜像的入口点配置 docker inspect mysql/mysql-router:8.0.32 | jq '.[0].Config.Entrypoint' # 提取并检查入口点脚本 docker run --rm --entrypoint cat mysql/mysql-router:8.0.32 /entrypoint.sh > entrypoint.sh chmod +x entrypoint.sh ./entrypoint.sh --help ``` ##### 2. 交互式调试 ```bash docker run -it --rm \ --network mysql-net \ -v /use01/docker/mysqlrouter:/etc/mysqlrouter \ --entrypoint sh \ mysql/mysql-router:8.0.32 # 在容器内手动运行 mysqlrouter --bootstrap mgr_user@mysql-master:3306 \ --conf-set-option=DEFAULT.name=router \ --conf-set-option=metadata_cache:Cluster01.bootstrap_server_addresses=mysql-master:3306,mysql-slave1:3306,mysql-slave2:3306 \ --conf-set-option=routing:read_write.bind_port=6446 \ --conf-set-option=routing:read_only.bind_port=6447 \ --conf-set-option=routing:read_write_split.bind_port=6450 \ --force ``` ##### 3. 日志分析 ```bash # 获取详细日志 docker run --rm \ -v /use01/docker/mysqlrouter:/etc/mysqlrouter \ mysql/mysql-router:8.0.32 \ mysqlrouter --bootstrap mgr_user@mysql-master:3306 --help > bootstrap_help.txt # 检查日志输出 docker logs mysql-router >& router_logs.txt ``` #### 验证连接 ```bash # 测试读写连接 mysql -h 127.0.0.1 -P 6446 -u mgr_user -p -e "SELECT @@server_id" # 测试只读连接 mysql -h 127.0.0.1 -P 6447 -u mgr_user -p -e "SELECT @@server_id" # 测试读写分离 mysql -h 127.0.0.1 -P 6450 -u mgr_user -p -e "START TRANSACTION; SELECT @@server_id; COMMIT" ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值