OpenHarmony恢复启动子系统init进程之启动FD代持服务 原创 精华

软通动力HOS
发布于 2022-9-14 09:08
浏览
4收藏

FD代持是按需启动的一个辅助扩展机制,按需启动进程可以保持退出前的fd状态句柄不丢失。按需启动进程退出前可将fd发送给init代持,再次启动后再从init获取fd。

代持原理:

OpenHarmony恢复启动子系统init进程之启动FD代持服务-鸿蒙开发者社区

代持流程:

按需启动进程退出前可将fd发送给init代持,再次启动后再从init获取fd。
init提供了相关接口供服务调用,服务进程退出前调用接口将fd通过支持IPC通信的socket发送给init代持,待该服务重新启动时,init将持有的该服务相关的fd句柄通过同样的方式返回给服务。
OpenHarmony恢复启动子系统init进程之启动FD代持服务-鸿蒙开发者社区

消息格式:

方法 说明
hold 由子服务发送给fdholder 服务,然后交给init进程代持
get 子服务请求fdholder,由fdholder返还fd给子服务
为避免其他进程访问,都需要验证gid,uid,pid。

发布fdholder

正常情况下,fd 是不能在进程间传递的,但是可以通过发布fd来达到目的。
代码:

{
    INIT_ERROR_CHECK(service != NULL, return, "Publish hold fds with invalid service");
    char fdBuffer[MAX_FD_HOLDER_BUFFER] = {};
    if (service->fdCount > 0 && service->fds != NULL) {
        size_t pos = 0;
        for (size_t i = 0; i < service->fdCount; i++) {
            /**
             * 技术要点1:  dup(fd) 重定向fd,同时会清除O_CLOEXEC
             *            O_CLOEXEC 标志本来用于防止fd泄露给子进程,这里清除这个标志,就是因为发布就是为了给子进程使用。
             */
            int fd = dup(service->fds[i]);
            if (fd < 0) {
                INIT_LOGE("Duplicate file descriptors of Service \' %s \' failed. err = %d", service->name, errno);
                continue;
            }
            
            if (snprintf_s((char *)fdBuffer + pos, sizeof(fdBuffer) - pos, sizeof(fdBuffer) - 1, "%d ", fd) < 0) {
                INIT_LOGE("snprintf_s failed err=%d", errno);
                return;
            }
            pos = strlen(fdBuffer);
        }
        fdBuffer[pos - 1] = '\0'; // Remove last ' '
        INIT_LOGI("fd buffer: [%s]", fdBuffer);
        
        /**
         * 技术要点2:  发布fds, 实际就是将fd设置到环境变量。在当前进程或子进程通过环境变量访问。
         *             #define ENV_FD_HOLD_PREFIX "OHOS_FD_HOLD_"  ,通过getenv("OHOS_FD_HOLD_fdfdfd")就能
         *           获取所有发布的fd。
         */
        char envName[MAX_BUFFER_LEN] = {};
        (void)snprintf_s(envName, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, ENV_FD_HOLD_PREFIX"%s", service->name);
        if (setenv(envName, fdBuffer, 1) < 0) {
            INIT_LOGE("Failed to set env %s", envName);
        }
        INIT_LOGI("File descriptors of Service \' %s \' published", service->name);
    }
}

就是发布一个环境变量,名称为: OHOS_FD_HOLD_servername, 将fd(可能有多个) 转变成字符串作为环境变量的值。 启动子服务进程之后,先去查找环境变量,获取它的值,分解出fd。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
5
收藏 4
回复
举报
3条回复
按时间正序
/
按时间倒序
麻辣香锅配馒头
麻辣香锅配馒头

这个需要结合前面的上电启动及创建设备节点一起看吗?

回复
2022-9-14 16:22:20
软通动力HOS
软通动力HOS

是的哦

回复
2022-9-15 09:28:52
软通田可辉
软通田可辉

好厉害呀

回复
2022-10-20 09:52:00
回复
    相关推荐