chromeos session manager 简介

本文主要介绍 session manager 对浏览器进程的管理过程,在读此之前可以阅读文章 session_manager简介

概述

针对关注的功能模块,绘制类图如下所示:
在这里插入图片描述SessionManagerService 模块:整个 session manager 的核心,根据源码中的注释信息,这个类提供运行浏览器的方法,监控浏览器运行状况,并在必要的时候重启浏览器。

模块1:监控浏览器进程的退出信号,并在浏览器进程退出时,清理浏览器进程创建的子进程,如果有必要会重启浏览器。

模块2:浏览器进程在 session manager 中的描述信息,提供了对浏览器进程的各种管理方法。

模块3:浏览器进程的活性检测模块,负责周期性的 ping 浏览器进程,如果浏览器进程在规定的时间内没有回复消息,会发送 SIGABRT 信号终止浏览器进程。

模块4:session manager 对外提供的一些其他 DBus 接口,例如允许浏览器进程通过 session manager 提供的接口来实现结束会话、保存登录密码等功能。

session manager 还提供了对安卓容器 、锁频功能、电源和虚拟机的管理,这里没有过多的关注。

SessionManagerService

session manager 是一个独立的进程,所以有独立的主函数入口,分析 session manager 是从文件 platform2\login_manager\session_manager_main.cc 入手的,按照 main() 函数的流程进行依次分析。

从上面的类图可以看出,SessionManagerService 是整个 session manager 的核心,所有的工作都围绕这个类进行。从 session_manager_main.cc 的 main() 函数也可以看出 SessionManagerService 重要,大概 130 行的主函数,有 100 行是为执行 new SessionManagerService 做准备的。

在 main() 函数中有一段代码如下:

// Allow waiting for all descendants, not just immediate children.
if (::prctl(PR_SET_CHILD_SUBREAPER, 1))
  PLOG(ERROR) << "Couldn't set child subreaper";

这段代码设置了 session manager 进程可以等待子进程的子进程,也就是说,如果 session manager 在等待浏览器进程退出,那么浏览器创建的子进程,例如 renderer 等,也会接受 session manager 的管理。

在执行 SessionManagerService 的构造函数时,函数体内只调用了一个函数 SetUpHandlers() ,这个函数主要是针对子进程(本文主要关注的是浏览器进程)退出时的信号注册关注这个事件的对象,设置捕获处理函数。

主函数中,在生成 SessionManagerService 后,执行这个对象的初始化操作,初始化成功之后,如果需要运行浏览器,就向线程消息循环中抛一个运行浏览器的任务,然后启动消息循环,整个主函数就差不多结束了。

在 SessionManagerService 的初始化过程中,主要是初始化 DBus 服务,获取锁屏、电源、虚拟机等的 DBus 代理对象,实例化一个浏览器活性检测的对象和一个 SessionManagerImpl 对象,最后启动 DBus 服务,至此就完成了初始化工作。

刚才提到“如果需要运行浏览器”,那是根据什么来判断是否要运行呢?

// This job encapsulates the command specified on the command line, and the
// runtime options for it.
auto browser_job = std::make_unique<BrowserJob>(
    command, env_vars, &checker, &metrics, &system, config,
    std::make_unique<login_manager::Subprocess>(uid, &system));
bool should_run_browser = browser_job->ShouldRunBrowser();

从代码片段可以看出,是根据 BrowserJob 对象来判断是否需要运行浏览器的,进一步深入分析,发现可以通过创建一个禁止浏览器重启的文件来让 BrowserJob 不启动浏览器,默认情况下这个文件是不存在的,所以会启动浏览器。

启动浏览器

在 session_manager_main.cc 主函数中,为浏览器启动做了大量的工作,主要是为浏览器启动准备参数,以及是否要对浏览器进行活性检测的判断设置,这些参数都保存在 BrowserJob 对象中。因此,启动浏览器的过程看上去就很简单了:

void SessionManagerService::RunBrowser() {
  browser_->RunInBackground();
  DLOG(INFO) << "Browser is " << browser_->CurrentPid();
  liveness_checker_->Start();
}

在 BrowserJob::RunInBackground() 函数中,就是进一步的整合启动参数,最终调用系统函数 execve() 执行真正的启动。

浏览器退出状态监控

在 SessionManagerService 的 SetUpHandlers() 方法中,会实例化一个 ChildExitDispatcher 对象,在这个类的构造函数中,会注册一个对 SIGCHLD 信号的处理函数, SIGCHLD 是子进程退出的信号。

在 SIGCHLD 信号的处理函数中,会通过 waitid 函数来等待 session manager 子进程状态改变,并收集子进程退出的原因,再将导致子进程退出的信号分发给前面注册的对象中去处理。关于 waitid() 函数的资料网上比较多,感兴趣可以搜索查看。

在这里比较感兴趣的是 SessionManagerService 对子进程退出原因的处理,可以进入到对应的成员函数 HandleExit() 中查看处理过程。

在 HandleExit() 中,首先判断当前退出的子进程是否为浏览器进程,如果不是处理就结束了,如果是浏览器进程,就会执行清理动作,关闭浏览器进程的所有子进程,关闭安卓容器以及虚拟机,如果需要运行浏览器,就会再次启动浏览器。

浏览器活性检测

因为只有在运行浏览器的时候才需要执行浏览器活性检测,所以活性检测的启动是在运行浏览器的代码中。

在 LivenessCheckerImpl 的 Start() 函数中,定义了一个 base::CancelableClosure 对象,然后向主线程消息循环中抛了一个延时任务,延时时间就是检测周期。

如果在进行下一次检测前,浏览器进程尚未对上一次的 ping 进行回复,就会终止浏览器进程。

如果已经回复了上一次的检测,就执行当前的检测,最后再向主消息循环抛一个延时任务,从而实现周期性的检测。

小结

session manager 功能不止这些,不过本文主要关注 session manager 对浏览器生命周期的管理,所以其他功能都直接忽略了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值