浏览器工作原理与实践--浏览上下文组:如何计算Chrome中渲染进程的个数

经常有朋友问到如何计算Chrome中渲染进程个数的问题,那么今天就来完整地解答这个问题。

在前面“04 | 导航流程”这一讲中我们介绍过了,在默认情况下,如果打开一个标签页,那么浏览器会默认为其创建一个渲染进程。不过我们在“04 | 导航流程”中还介绍了同一站点的概念,如果从一个标签页中打开了另一个新标签页,当新标签页和当前标签页属于同一站点的话,那么新标签页会复用当前标签页的渲染进程。

具体地讲,如果我从极客邦(www.geekbang.org) 的标签页中打开新的极客时间(time.geekbang.org) 标签页,由于这两个标签页属于同一站点(相同协议、相同根域名),所以他们会共用同一个渲染进程。你可以看下面这张Chrome的任务管理器截图:

多个标签页运行在同一个渲染进程

观察上图,我们可以看到,极客邦官网和极客时间标签页都共用同一个渲染进程,该进程ID是84748。

不过如果我们分别打开这两个标签页,比如先打开极客邦的标签页,然后再新建一个标签页,再在这个新标签页中打开极客时间,这时候我们可以看到这两个标签页分别使用了两个不同的渲染进程。你可以参看下图:

多个标签页运行在不同的渲染进程中

那么到了这里,你一定会很好奇,既然都是同一站点,为什么从A标签页中打开B标签页,就会使用同一个渲染进程,而分别打开这两个标签页,又会分别使用不同的渲染进程?

标签页之间的连接

要搞清楚这个问题,我们要先来分析下浏览器标签页之间的连接关系。

我们知道,浏览器标签页之间是可以通过JavaScript脚本来连接的,通常情况下有如下几种连接方式:

第一种是通过<a>标签来和新标签建立连接,这种方式我们最熟悉,比如下面这行代码是从极客邦标签页里面拷贝过来的:

<a  href="https://time.geekbang.org/" target="_blank" class="">极客时间</a>

这是从极客邦官网中打开极客时间的链接,点击该链接会打开新的极客时间标签页,新标签页中的window.opener的值就是指向极客邦标签页中的window,这样就可以在新的极客时间标签页中通过opener来操作上个极客邦的标签页了。这样我们可以说,这两个标签页是有连接的。

另外,还可以通过JavaScript中的window.open方法来和新标签页建立连接,演示代码如下所示:

new_window = window.open("http://time.geekbang.org")

通过上面这种方式,可以在当前标签页中通过new_window来控制新标签页,还可以在新标签页中通过window.opener来控制当前标签页。所以我们也可以说,如果从A标签页中通过window.open的方式打开B标签页,那么A和B标签页也是有连接的。

其实通过上述两种方式打开的新标签页,不论这两个标签页是否属于同一站点,他们之间都能通过opener来建立连接,所以他们之间是有联系的。在WhatWG规范中,把这一类具有相互连接关系的标签页称为浏览上下文组( browsing context group)。

既然提到浏览上下文组,就有必要提下浏览上下文,通常情况下,我们把一个标签页所包含的内容,诸如window对象,历史记录,滚动条位置等信息称为浏览上下文。这些通过脚本相互连接起来的浏览上下文就是浏览上下文组。如果你有兴趣,可以参考下规范文档。

也就是说,如果在极客邦的标签页中,通过链接打开了多个新的标签页,不管这几个新的标签页是否是同一站点,他们都和极客邦的标签页构成了浏览上下文组,因为这些标签页中的opener都指向了极客邦标签页。

Chrome浏览器会将浏览上下文组中属于同一站点的标签分配到同一个渲染进程中,这是因为如果一组标签页,既在同一个浏览上下文组中,又属于同一站点,那么它们可能需要在对方的标签页中执行脚本。因此,它们必须运行在同一渲染进程中。

现在我们清楚了浏览器是怎么分配渲染进程的了,接下来我们就可以来分析文章开头提的那个问题了:

既然都是同一站点,为什么从A标签页中打开B标签页,就会使用同一个渲染进程? 而分别打开这两个标签页,又会分别使用不同的渲染进程?

首先来看第一种,在极客邦标签页内部通过链接打开极客时间标签页,那么极客时间标签页和极客邦标签页属于同一个浏览上下文组,且它们属于同一站点,所以浏览器会将它们分配到同一个渲染进程之中。

而第二种情况就简单多了,因为第二个标签页中并没有第一个标签页中的任何信息,第一个标签页也不包含任何第二个标签页中的信息,所以他们不属于同一个浏览上下文组,因此即便他们属于同一站点,也不会运行在同一个渲染进程之中。下面是我画的计算标签页的流程图,你可以参考下:

计算标签页使用的渲染进程数目

一个“例外”

好了,现在我们清楚了Chrome浏览器为标签页分配渲染进程的策略了:

  1. 如果两个标签页都位于同一个浏览上下文组,且属于同一站点,那么这两个标签页会被浏览器分配到同一个渲染进程中。

  2. 如果这两个条件不能同时满足,那么这两个标签页会分别使用不同的渲染进程来渲染。

现在你可以想一下,如果从A标签页中打开B标签页,那我们能肯定A标签页和B标签页属于同一浏览上下文组吗?

答案是“不能”,下面我们就来看个例子,在“04 | 导航流程”的留言区中,ID为“芳华年月”的朋友就提出了这样的一个问题:

请问老师,https://linkmarket.aliyun.com内新开的标签页都是新开一个渲染进程,能帮忙解释下吗?

我们先来复现下“芳华年月”所描述的现象,首先打开linkmarket.aliyun.com这个标签页,再在这个标签页中随便点击两个链接,然后就打开了两个新的标签页了,如下图所示:

“例外”情况

我通过A标签页中的链接打开了两个新标签页,B和C,而且我们也可以看出来,A、B、C三个标签页都属于同一站点,正常情况下,它们应该共用同一个渲染进程,不过通过上图我们可以看出来,A、B、C三个标签页分别使用了三个不同的渲染进程。

既然属于同一站点,又不在同一个渲染进程中,所以可以推断这三个标签页不属于同一个浏览上下文组,那么我们接下来的分析思路就很清晰了:

  1. 首先验证这三个标签页是不是真的不在同一个浏览上下文组中;

  2. 然后再分析它们为什么不在同一浏览上下文组。

为了验证猜测,我们可以通过控制台,来看看B标签页和C标签标签页的opener的值,结果发现这两个标签页中的opener的值都是null,这就确定了B、C标签页和A标签页没有连接关系,当然也就不属于同一浏览上下文组了。

验证了猜测,接下来的我们就是来查查,阿里的这个站点是不是采用了什么特别的手段,移除了这两个标签页之间的连接关系。

我们可以看看实现链接的HTML文件,如下图所示:

链接使用了rel = noopener

通过上图,我们可以发现,a链接的rel属性值都使用了noopener 和 noreferrer,通过noopener,我们能猜测得到这两个值是让被链接的标签页和当前标签页不要产生连接关系。

通常,将noopener的值引入rel属性中,就是告诉浏览器通过这个链接打开的标签页中的opener值设置为null,引入noreferrer是告诉浏览器,新打开的标签页不要有引用关系。

好了,到了这里我们就知道了,通过linkmarket.aliyun.com标签页打开新的标签页要使用单独的一个进程,是因为使用了rel= noopener的属性,所以新打开的标签页和现在的标签页就没有了引用关系,当然它们也就不属于同一浏览上下文组了。这也同时解答了“芳华年月”所提出的问题。

站点隔离

上面我们都是基于标签页来分析渲染进程的,不过我在“35|安全沙箱”中介绍过了,目前Chrome浏览器已经默认实现了站点隔离的功能,这意味着标签页中的iframe也会遵守同一站点的分配原则,如果标签页中的iframe和标签页是同一站点,并且有连接关系,那么标签页依然会和当前标签页运行在同一个渲染进程中,如果iframe和标签页不属于同一站点,那么iframe会运行在单独的渲染进程中。

我们先来看下面这个具体的例子吧:

<head>
    <title>站点隔离:demo</title>
    <style>
        iframe {
            width: 800px;
            height: 300px;
        }
    </style>
</head>
<body>
    <div><iframe src="iframe.html"></iframe></div>
    <div><iframe src="https://www.infoq.cn/"></iframe></div>
    <div><iframe src="https://time.geekbang.org/"></iframe></div>
    <div><iframe src="https://www.geekbang.org/"></iframe></div>
</body>
</html>

在Chrome浏览器中打开上面这个标签页,然后观察Chrome的任务管理,我们会发现这个标签页使用了四个渲染进程,如下图所示:

iframe使用单独的渲染进程

结合上图和HTML代码,我们可以发现,由于InfoQ、极客邦两个iframe与父标签页不属于同一站点,所以它们会被分配到不同的渲染进程中,而iframe.html和源标签页属于同一站点,所以它会和源标签页运行在同一个渲染进程中。下面是我画的计算iframe使用渲染进程数目的流程图,你可以对照着参考下:

计算iframe所使用的渲染进程数目

总结

好了,本节的内容就介绍到这里,下面我来总结下本文的主要内容:

首先我们使用了两种不同的方式打开两个标签页,第一种是从A标签页中通过链接打开了B标签页,第二种是分别打开A和B标签页,这两种情况下的A和B都属于同一站点。

通过Chrome的任务管理器我们发现,虽然A标签页和B标签页都属于同一站点,不过通过第一种方式打开的A标签页和B标签页会共用同一个渲染进程,而通过第二种方式打开的两个标签页却分别使用了两个不同的渲染进程。

这是因为,使用同一个渲染进程需要满足两个条件:首先A标签页和B标签页属于同一站点,其次A标签页和B标签页需要有连接关系。

接着,我们分析了一个“例外”,如果在链接中加入了rel=noopener属性,那么通过链接打开的新标签页和源标签页之间就不会建立连接关系了。

最后我们还分析了站点隔离对渲染进程个数的影响,如果A标签页中的iframe和A标签页属于同一站点,那么该iframe和A标签页会共用同一个渲染进程,如果不是,则该iframe会使用单独的渲染进程。

好了,到了这里相信你已经会计算渲染进程的个数了。

在最后我们还要补充下同源策略对同一站点的限制,虽然Chrome会让有连接且属于同一站点的标签页运行在同一个渲染进程中,不过如果A标签页和B标签页属于同一站点,却不属于同源站点,那么你依然无法通过opener来操作父标签页中的DOM,这依然会受到同源策略的限制。

简单地讲,极客邦和极客时间属于同一站点,但是他们并不是同源的,因为同源是需要相同域名的,虽然根域名geekbang.org相同,但是域名却是不相同的,一个是time.geekbang.org,一个是www.geekbang.org, 因此浏览器判断它们不是同源的,所以依然无法通过time.geekbang.org标签页中的opener来操作www.geekbang.org中的DOM。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/557877.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt | 远程仓库

git | 基本操作 01 远程仓库 在了解之前&#xff0c;先注册github(gitee或者gitcode等等)账号&#xff0c;由于你的本地Git仓库和github仓库之间的传输是通过SSH加密的&#xff0c;所以需要一点设置&#xff1a; 第一步&#xff1a;创建SSH Key。在用户主目录下&#xff0c;看看…

姿态估计-人脸识别mesh-3d手势识别-3d目标检测-背景分割-人脸关键点

往期热门博客项目回顾&#xff1a;点击前往 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别-3d姿态识别 深度学习小白学习路线 AI健身教练-引体向上…

UE4 相机围绕某点旋转

关卡&#xff08;一个相机CameraActor&#xff0c;一个Cube(名叫Target)&#xff09;&#xff1a; 关卡蓝图里的逻辑(为了大家看得清楚&#xff0c;特意连得很紧凑&#xff0c;也比较乱&#xff0c;不然一张截图放不下)&#xff1a; 只对Yaw 只Pitch: 同样对Roll: 围绕任…

Modelsim与Verilog入门

0.什么是Modelsim&#xff1f; Modelsim是一个支持多语言的仿真环境&#xff0c;比如我知道的Verilog和VHDL语言都可以在里边使用&#xff0c;这俩都是硬件描述语言&#xff1b; 即就是个软件&#xff0c;你可以用Verilog语言来写代码&#xff0c;然后编译&#xff0c;仿真出…

C++学习进阶:异常

目录 1.异常处理机制 1.1.抛异常和捕获异常 1.1.1.异常机制的基本场景 1.1.2.函数调用中异常栈展开的匹配规则&#xff1a; 1.2.异常机制的实际应用场景 2.异常相关知识 2.1.异常安全和异常重新抛出 2.2.noexcept关键字 2.3.异常的优缺点 1.异常处理机制 我们在C语言…

Finding a needle in Haystack: Facebook’s photo storage——论文泛读

OSDI 2010 Paper 分布式元数据论文阅读笔记整理 问题 到2010年为止&#xff0c;用户已经在Facebook上传了超过650亿张照片&#xff0c;对于每个上传的照片&#xff0c;Facebook生成并存储四个不同大小的图像&#xff0c;导致目前存储了超过2600亿张图片&#xff0c;相当于超过…

AQS(AbstractQueuedSynchronizer)队列同步器源码解读

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1. 前言 2. AOS、AQS、AQLS的区别 3. AQS的底层原理 3.1. 核心思想 3.2. 数…

Qt 项目文件(.pro)概述

Qt 项目pro文件 引言一、pro文件初探二、部分参数详解 引言 Qt工程项目由项目文件&#xff08;.pro&#xff09;进行管理。qmake使用文件中的信息生成Makefile&#xff0c;其中包含构建每个项目所需的所有命令。pro文件通常包含源文件和头文件的列表、常规配置信息以及任何特定…

ST-GCN模型详解(+openpose)

ST-GCN模型详解&#xff08;openpose&#xff09; 一、什么是ST-GCN呢 基于骨架的动作识别&#xff08;Skeleton-Based Action Recognition&#xff09;主要任务是从一系列时间连续的骨骼关键点&#xff08;2D/3D&#xff09;中识别出正在执行的动作。因为牵涉到骨骼框架这种…

CentOS7升级openssl

文章目录 一 系统环境二 操作步骤三 版本检查 一 系统环境 公司服务器等保要求&#xff0c;修复openssl的高危漏洞。 本机使用centos7.9系统&#xff0c;openssl版本是1.0.2k&#xff0c;计划升级到1.1.1q 在执行下列操作前&#xff0c;务必要打快照做好备份&#xff0c;以防升…

030——从GUI->Client->Server->driver实现对红外遥控的控制

目录 1、 解决韦东山老师irda模块中断申请失败的bug 2、 client添加处理程序 3、 添加服务器处理程序和驱动处理句柄 4、 处理数据读出不准确问题 5、 修改后的展示 1、 解决韦东山老师irda模块中断申请失败的bug irda需要通过中断来触发读操作&#xff0c;申请中断需要引…

Octopus v2:斯坦福的嵌入设备专用大模型

斯坦福大学推出了 Octopus v2&#xff0c;这是一种突破性的设备上语言模型&#xff0c;旨在解决与现有模型相关的延迟、准确性和隐私问题。 NSDT工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑…

源码篇--Nacos服务--中章(1):Nacos服务端的启动

文章目录 前言一、Nacos Console 启动入口&#xff1a;二、启动过程&#xff1a;2.1 容器启动监听器&#xff1a;2.1.1 调整启动标识为正在启动状态&#xff1a;2.1.2 环境准备阶段&#xff1a;2.1.3 容器环境准备&#xff1a;2.1.4 自定义的环境变量 设置&#xff1a;2.1.5 服…

Spectre-v2 以及 Linux Retpoline技术简介

文章目录 前言一、Executive Summary1.1 Spectre-v2: Branch Predictor Poisoning1.2 Mitigating Spectre-v2 with Retpolines1.3 Retpoline Concept 二、BackgroundExploit Composition 三、(Un-)Directing Speculative Execution四、Construction (x86)4.1 Speculation Barri…

测试人员通常遇到的“坑”

网上看到一个帖子&#xff0c;从事多年的测试从业者&#xff0c;吐槽测试过程中遇到的“坑”&#xff0c;感觉比较有意思&#xff0c;我在工作当中也遇到通常的问题&#xff0c;看得出这位网友比较喜欢总结&#xff0c;帖子地址奉上&#xff0c;有兴趣的可以浏览一下&#xff1…

bug(警告):[vue-router] Duplicate named routes definition: …

查看警告&#xff1a;[vue-router] Duplicate named routes definition——翻译[vue-router]重复命名路由定义 小编劝诫&#xff1a;当我们在开发过程中警告也一定不要忽略&#xff0c;虽然你在本地跑代码时这些警告影响项目的正常运行&#xff0c;但是会让你产生误区&#xff…

大模型日报|今日必读的8篇大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.EdgeFusion&#xff1a;端侧文本到图像生成&#xff0c;只需不到一秒 用于文本到图像生成的稳定扩散&#xff08;SD&#xff09;技术需要大量计算&#xff0c;这对其实际应用构成了重大障碍。为此&#xff0c;最近…

Oracle進階SQLDay03

一、函數進階復習 1、行轉列 select 用水儿量&#xff08;噸&#xff09; 统计项, sum(case when t_account.month01 then USENUM end) 一月, sum(case when t_account.month02 then USENUM end) 二月, sum(case when t_account.month03 then USENUM end) 三月, sum(case when …

STM32学习和实践笔记(15):STM32中断系统

中断概念 CPU执行程序时&#xff0c;由于发生了某种随机的事件(外部或内部)&#xff0c;引起CPU暂 时中断正在运行的程序&#xff0c;转去执行一段特殊的服务程序(中断服务子程序 或中断处理程序)&#xff0c;以处理该事件&#xff0c;该事件处理完后又返回被中断的程序 继…

飞桨Ai(二)paddle使用CPU版本可以正常识别,切换为GPU版本时无法识别结果

一、问题描述&#xff1a; 刚开始用paddle的CPU版本&#xff0c;对训练好的模型进行推理&#xff0c;正常识别出想要的结果后来尝试使用paddle的GPU版本&#xff0c;然后发现识别出来是空的 二、系统思路&#xff1a; 最终系统环境如下&#xff1a; 系统&#xff1a;win10 …
最新文章