《WebKit 技术内幕》学习之十(2): 插件与JavaScript扩展
2 Chromium PPAPI插件
2.1 原理
插件其实是一种统称,表示一些动态库,这些动态库根据定义的一些标准接口可以跟浏览器进行交互,至于这个标准接口是什么都可以,重要的是大家都遵循它们,NPAPI接口标准只是其中的一种,因为它被广泛使用,所以被提到的次数也最多。本节介绍的PPAPI也是一种浏览器和插件交互的接口标准,该标准是由Google提出,在Chromium项目中获得支持。
PPAPI的提出是因为NPAPI的可移植性和性能存在比较大的问题,特别是针对跨进程的插件,同时还有插件需要2D和3D绘图、声音等问题时候就更为棘手。早期的阶段就是要解决这些问题,同时为了赢得插件厂商的支持,尽可能地使用原来NPAPI的接口。现在,随着PPAPI的不断发展,接口不断发生改变。后来,PPAPI也被用在Native Client技术中,之后也被逐渐地修改,直到现在的样子,完整的列表可以查看链接http://code.google.com/p/ppapi/w/list。
那么,为什么PPAPI能够提供较高性能的绘图和声音等解决方案呢?前面我们提到,在现在的NPAPI插件系统中,通常的做法是,当网页需要显示该插件的时候或者需要更新的时候,它会发送一个失效(Invalidate)的通知,让插件来绘制它们。而在PPAPI插件机制中,它引入了一个保留(Retained)模式,其含义是浏览器始终保留一个后端存储空间,用来表示上一次绘制完的区域。这个很有用,因为PPAPI插件通常是跨进程的,所以浏览器可以绘制网页而不需要锁,与此同时插件进程能够在后台绘制新的结果。
PPAPI插件有两种运行模式,受信(Trusted)插件和非受信(Untrusted)插件。对于受信的PPAPI插件,它可以在Renderer进程中运行,也可以在另外的进程中运行。对于新版本的实现,架构设计都是基于IPC来设计的。对于非受信的PPAPI插件,则可以借助于使用NativeClient技术来安全运行。受信插件是与平台相关的,可以调用平台相关的接口。而对于非受信插件而言,它们可以是与平台无关的代码,可以调用NativeClient提供的有限接口,而不能调用其他接口,这个后面再介绍。
在Chromium中,NPAPI和PPAPI插件同时得到支持,都可以在“chrome://plugins”来查看,前面已经提到过。有趣的是,对于同一个功能的插件,甚至可能有两个不同的版本,如图10-8所示Flash的NPAPI插件和PPAPI插件实现。
图10-8 Chrome浏览器的NPAPI插件和PPAPI插件
PPAPI插件同样使用“embed”或者“object”元素,这让网页看起来没什么大的区别,所以对于WebKit而言,它根本不会区分背后的是NPAPI插件还是PPAPI插件,差别在于调用的接口不一样而已,这样做的好处显而易见。
2.2 结构和接口
2.2.1 代码结构
因为PPAPI插件对于WebKit而言是透明的,所以这里不再介绍WebKit中支持该插件的基础设施。Chromium支持跨进程的PPAPI插件机制,所以在代码结构上可以充分看到这一点。Chromium项目中有3个目录用来支持这一机制,详细结构如图10-9所示。
图10-9 支持PPAPI插件机制的代码目录结构
首先是chrome目录,它包含Renderer进程和Browser进程对于PPAPI插件的支持代码,主要是资源的实现类。
其次是content目录,同样也包含了资源的实现类,但是同时也有支持跨进程机制的代码,这会在后面的工作过程图中有所体现。
最后是ppapi目录,当然支持PPAPI插件的代码都是在该目录中,包括支持跨进程的基础代码,它们被Renderer进程和Browser进程的支持代码所使用。
读者可能好奇为什么chrome目录下的相关文件不直接放在content/目录下,这主要取决于Chromium项目的层次化结构。content目录下包含一些公共或者基础的设施,而chrome/目录则是跟浏览器密切相关的。例如对于PPAPI插件机制而言,它将PDF和Flash都放在该目录下,而将文件等放在content目录下。
2.2.2 应用程序编程接口
同NPAPI的NPN和NPP开头的接口相似,PPAPI也需要双向调用的编程接口,PPAPI提供了浏览器调用插件的接口,同时更是提供了众多插件调用浏览器各种功能的接口,这非常不一样,因为功能更为强大。
这些接口的标准定义文件都位于上面所述的目录ppapi/api中,它们都使用一种接口定义语言(IDL,Interface Definition Language)来描述。IDL是一种标准,有兴趣的读者可以查阅它的基本语法。其中以ppb_(ppapi browser)开头的接口文件表示这是由浏览器实现,被插件库所调用;以ppp_(ppapi plugin)开头的接口文件表示这是由插件实现,被浏览器所调用;而其他以pp_开头的接口文件表示共享的接口定义,两边都需要使用,主要是一些基础类定义等。
不同于NPAPI只是提供C接口,PPAPI既提供了C接口,同时又提供了C++接口。C接口主要是函数指针和结构为主,而C++接口则是提供各种作用的类,它们分别位于目录ppapi/c和ppapi/cpp下。因为两个定义的功能是一致的,之后我们都以C++接口为例来解释PPAPI插件机制。
公共部分的接口包括各个基础数据,如时间、大小、矩形和资源,这些类会作为后面定义接口的参数来传递,对应的接口例如PP_Time、PP_Size、PP_Rect和PP_Resource。这里面非常重要的接口是PP_Resource,它表示各种类型的资源,例如文件资源、音频资源、图像资源、图形资源等。
由插件实现的接口大致包括以下几个部分:第一部分是插件模块和插件实例,用于初始化和关闭插件的管理插件功能的接口,例如PPP_InitializeModule()、PPP_ShutdownModule()。而插件的实例类,表示一个插件的实例对象,也就是Interface PPP_Instance,这里面包含多个函数,如DidCreate、DidDestroy等,表示当创建插件之后,浏览器调用它们,以便插件能够做一些后续的辅助工作。第二部分是一些事件的通知接口,表示浏览器需要派发一些消息给插件,典型的包括鼠标事件、通用消息传递接口、3D图形上下文丢失事件和鼠标锁定事件等。
由浏览器实现的接口,主要提供各种能力给插件使用,这其中包括2D和3D图形绘制接口、文件IO、文件系统、鼠标事件、网络、游戏手柄、时间等,这些都是PPAPI机制中定义的可以被浏览器调用的资源及其编程接口,读者会发现这些主要都是为游戏的需求服务的,实际上这些机制就是为了高性能的游戏而设计的。
2.3 工作过程
2.3.1 基础设施
对于PPAPI插件的跨进程架构,同NPAPI插件的跨进程架构非常类似,可以说基本相同。同样当网页中出现一个“embed”元素的时候,PPAPI插件进程会为它创建一个插件实例,这里不再赘述。
对于插件模块和实例接口,由插件进程直接调用并根据需要加载和创建它们,非常的简单明了。在PPAPI插件机制中,复杂的是资源的调用,也就是浏览器提供给插件使用的各种资源接口,所以下面重点介绍围绕资源的基础设施。
图10-10描述了跨进程模式下PPAPI插件机制中资源是如何被插件调用的。如同前面一样,PPAPI的插件是在插件进程中被加载的,当它需要使用插件的时候,通过图中Thunk设施将C接口转成C++接口来调用相应的PluginResource类。该类是所有资源的基类,是一个代理类(只是将请求转发给真正的实现者),负责发送请求给其他进程,拥有接受其他进程发过来的调用结果的能力。发送请求由相应的其他类来帮助,在这里是PluginDispatcher类和HostDispatcher类。它们都会使用IPC::Channel来发送消息,消息会被Browser进程和Renderer进程中的BrowserPpapiHost类和RenderPpapiHost类处理(它们依赖ppapi/host的基类),这些请求会发送给ResourceHost类来处理,以调用真正的实现函数。读者发现这两个进程都有ResourceHost的子类,这是因为某些资源的实现在Renderer进程完成,例如2D和3D图形资源,但是有些类必须在Browser进程中处理,如文件和文件系统等。
图10-10 跨进程的PPAPI插件机制中支持资源的基础设施
2.3.2 工作过程
这里以Chromium中PPAPI的一个使用2D绘图的例子来说明PPAPI插件的工作过程,该例子位于目录ppapi/examples/2d下,主要有两个部分,一个是个简单的HTML网页文件(2d.html),另外一个就是实现插件的文件(paint_manager_example.cc)。示例代码10-1是使用插件的网页代码,示例代码主要是“embed”元素,同NPAPI插件的使用方式完全一模一样,下面会逐步讲解PPAPI插件的源代码,以及该插件是如何和该网页一起工作的。
示例代码10-1 使用插件的网页代码
<html><head><title>2D Example</title></head><body><embed id="plugin" type="application/x-ppapi-example-2d"></body></html>
首先当然是插件的创建过程。在WebKit中,对于PPAPI和NPAPI的支持都是类似的,所以可以回顾10-7中的NPAPI插件被创建的过程,二者同样根据MIME类型来查找PPAPI插件机制,如果Chromium发现查找到的是一个PPAPI插件而不是NPAPI插件,那么在创建WebPluginContainerImpl对象的时候,就会首先创建一个WebPlugin子类的对象。注意,这里不是一个WebPluginImpl对象,而是一个PepperWebPluginImpl对象。之后它就发送消息到插件进程,请求创建一个插件的实例。回到插件进程,它会根据插件的注册信息查找需要的插件并调用它的构造函数来初始化该插件的模块,如示例代码10-2所示的CreateModule方法。之后需要调用该方法返回的对象来创建一个插件实例的对象,如示例代码中的CreateInstance方法,会创建一个插件类自定义的一个示例。
示例代码10-2 插件的实现代码部分节选
class MyModule : public pp::Module {public:virtual pp::Instance* CreateInstance(PP_Instance instance) {return new MyInstance(instance);}};namespace pp {Module* CreateModule() {return new MyModule();}}
根据示例代码10-2和示例代码10-3,当MyInstance被创建的时候,Chromium会创建PPP_Proxy_Instance对象,该对象接收从Renderer进程传递过来的关于该实例的状态消息,如插件视图改变、销毁等,然后再调用插件的相应接口,前面说过这些接口是在插件中实现并由浏览器调用的。
其次来了解资源的创建,一个插件实例可能会用到多个资源,如绘图资源、文件资源等,示例代码10-3所示的OnPaint函数使用到了2D绘图资源。由于它使用了PaintManager类,当需要更新视图的时候,该类需要创建一个Graphics2D资源对象。
示例代码10-3 插件的实例类自定义实现
class MyInstance : public pp::Instance, public pp::PaintManager::Client {public:MyInstance(PP_Instance instance) {…}virtual bool HandleInputEvent(…) { … }virtual void OnPaint(pp::Graphics2D& graphics_2d, …) { … }private:pp::PaintManager paint_manager_;};
为了详细说明它的调用过程,图10-11和图10-12描述了资源类对象的创建和资源类对象接口的调用过程,分别以插件进程和Renderer进程的交互为例,而插件进程和Browser进程的交互则是类似的情况。
图10-11 Chromium创建PPAPI插件的资源对象的过程
图10-11包括两个步骤,第一个步骤在插件进程中完成,第二个步骤在Renderer进程中完成。当PPAPI插件需要创建一个资源对象的时候,会通过PPAPI的C接口调用Chromium内部的实现,Thunk层将其转换成C++风格的调用。在插件进程中,会有一个工厂类来创建不同类型的资源对象。本例中Graphics2DResource对象在创建的同时会发送一个消息到Renderer进程,这就是第二步骤。Renderer进程同样包含一个能够创建不同类型ResourceHost对象的工厂类,以帮助完成资源对象的创建。
图10-12 PPAPI插件调用资源对象接口的过程
图10-12描述了当资源对象创建完之后,插件需要调用资源对象的接口来完成特定的操作,这一过程可以包含三个步骤,其发生在两个进程中,图中已有完整描述。首先,当然还是插件进程接收到插件的调用请求,并把请求发送给Renderer进程。其次是Renderer进程接收响应,然后执行特定的操作,并将结果值返回或者通知插件进程该动作执行完成。最后是插件进程接收到返回值或者动作执行完的消息,如果需要,它还可以调用插件的函数来通知插件。当然,某些调用不需要从Renderer进程返回结果到插件进程,所以前两步是必需的,但是第三步却是可选的。
2.4 Native Client
2.4.1 基本原理
NativeClient,也简称为NaCl,是一种沙箱技术,它能够提供给平台无关的不受信本地代码一个安全的运行环境,可以针对那些计算密集型的需求,例如游戏引擎、可视化计算、大数据分析、3D图形渲染等,这些场合只需要访问有限的一些本地接口,不需要通过网络服务来计算,以免占用额外的带宽资源。同时,它能够比较方便地将原来使用传统语言例如C++编写的库直接移植到Web平台中。它同WebGL、WebAudio这样的技术所解决的问题相似,但是途径不同,因为这些技术是规范(或者草案),而NativeClient技术是Google提出的。使用NativeClient能够将很多本地库的能力轻易地提供给网页使用,而不需要复杂的移植过程,给重用带来很大的方便。
本身PPAPI和NativeClient没有必然联系,两者解决的是不同方面的问题:PPAPI提供插件机制;NativeClient使用PPAPI的插件机制将使用NativeClient技术编译出来的本地库运行同浏览器交互起来。只是目前NativeClient是基于PPAPI接口来实现的,其实之前NativeClient也曾经基于NPAPI接口来实现,所以能够在Firefox、Safari和Opera浏览器中运行(目前显然不能了)。
因为NativeClient使用PPAPI来提供一个安全的运行环境,本身它也是一个PPAPI插件,图10-13就是Chrome浏览器中一个PPAPI插件——NativeClient。同其他的PPAPI插件不一样,它是一个在Renderer进程中运行的插件,因为这个插件显然是受信的,如图中的“Type: PPAPI(in-process)”。
图10-13 NativeClient的PPAPI插件
所以,如果需要在网页加入代码<embed id="plugin" type="application/x-nacl">表明使用了NaCl技术,对于WebKit而言,它就是调用一个插件(不知是什么类型的插件),对于PPAPI技术而言,它就是调用了内嵌的NaCl PPAPI插件。因为NaCl还需要调用开发者的本地库,所以它还需要跟本地库来交互,下面来介绍PPAPI插件之后的技术。
NaCl本质上是一个运行环境,该子系统提供了很少的一些受限系统调用接口和资源的抽象,本地库只能调用它们,而不能任意使用系统调用。与沙箱模型的不同在于,NaCl是将一个第三方开发的代码库运行在受限的环境中,而沙箱模型是将一个进程运行在受限环境中。NaCl提供编译工具,将使用C/C++代码编写的代码编译生成它能运行的可执行格式——nexe。本地代码调用的也都是本地接口,同JavaScript的交互都由NaCl机制和PPAPI机制来完成。
为了直观理解NaCl机制,用图10-14描述了它的架构图,该图参考Chromium官方网站的示意图,为进行了一些删减和修改。
图10-14 使用PPAPI技术的NaCl机制
首先研究一下Renderer进程,如果没有后面的部分,NaCl插件和其他PPAPI插件没有什么特别的差别,同样通过PPAPI跟渲染引擎进行通信。但是这里NaCl插件只是一个桥接工作,它将同浏览器(也可以说渲染引擎)的交互交接到使用NaCl技术的本地可执行库“nexe”。
然后,Chromium会创建一个新的进程,该进程使用了沙箱技术,只能访问特定的系统接口,这样限定了该进程中的任何库都不能超越它们。在Renderer进程中的NaCl插件使用消息传递机制同sel_ldr进程通信。在消息机制之上是一种称为SPRC(简单的进程远程调用技术),该机制可以实现PPAPI的跨进程调用。不过目前插件同NaCl的实现之间的通信机制SRPC已经不支持,都是通过一个新的接口PostMessage来实现的,该接口意味着都是通过消息机制来进行的。
最后,sel_ldr提供的环境能够运行nexe,从图10-14中可以看出,nexe是不受信的部分,但是没关系,该机制可以用一个沙箱来将它运行在限定的sel_ldr进程中,nexe没有办法使用NaCl提供的接口之外的系统接口,从而保证了安全。nexe是本地代码库,所以跟平台相关,例如对于32位和64位系统,需要两份不同的代码库,这同时也造成了库的冗余,有没有什么好的办法能够解决这个问题呢?在最近的版本中,Google的工程师开始将LLVM技术引入到NaCl机制中,这就是pNaCl技术。
2.4.2 pNaCI
nexe需要不同的版本,一个关键的问题在于NaCl提供的编译工具只能将NaCl的实现直接编译成同硬件架构相关的本地代码,所以不同的平台需要生成不同的本地库。pNaCl提供了一套新的工具,该工具能够将C/C++代码编译成LLVM字节码,读者回忆一下图9-27中关于LLVM的基本结构,LLVM能够将C/C++代码转成字节码,该字节码是平台无关的,而且该字节码可以保存起来,当字节码在某个平台上运行的时候,LLVM的后端能够根据字节码生成特定平台的本地代码。
回到pNaCl上来,使用了LLVM技术很明显地能够带来减少库的冗余性的好处,这样nexe就可以变成pexe(portable exe)。对于如何使用pNaCl,这里不再介绍,官方网站上有非常详细的介绍,感兴趣的读者请查阅下面的网页:http://www.chromium.org/nativeclient/pnacl/developing-pnacl。
相关文章:

《WebKit 技术内幕》学习之十(2): 插件与JavaScript扩展
2 Chromium PPAPI插件 2.1 原理 插件其实是一种统称,表示一些动态库,这些动态库根据定义的一些标准接口可以跟浏览器进行交互,至于这个标准接口是什么都可以,重要的是大家都遵循它们,NPAPI接口标准只是其中的一种&a…...
【头歌-数据分析与实践-python】数据分析与实践-python——python基础
注意 : 本文档仅供参考使用,本章节程序绝大多数程序面向对象输出,一旦测试用例改变,会导致无法通过,请悉知 ! ! ! 请勿盲目使用 数据分析与实践-python——python基础 数据分析与实践-python——python基础 数据分析与…...

【数据库原理】(37)Web与数据库
随着网络的高速发展和网络服务的日趋完善,网络上的信息量呈几何级数增长。为了有效地组织、存储、管理和使用网上的信息,数据库技术被广泛地应用于网络领域。特别是在Internet上,已建立了数以万计的网站,其中大中型网站的后台大多…...

STM32 TIM输出比较、PWM波形
单片机学习! 目录 一、输出比较简介 二、PWM简介 三、输出比较通道 3.1通用定时器的输出比较部分电路 3.2高级定时器的输出比较部分电路 四、输出模式控制器 五、PWM基本结构 六、PWM参数计算 总结 前言 文章讲述STM32定时器的输出比较功能,它主…...
React16源码: React中的updateClassComponent的源码实现
ClassComponent 的更新 1 ) 概述 在 react 中 class component,是一个非常重要的角色它承担了 react 中 更新整个应用的API setStateforceUpdate 在react当中,只有更新了state之后,整个应用才会重新进行渲染在 class component 中…...

Mybatis 动态SQL(set)
我们先用XML的方式实现 : 把 id 为 13 的那一行的 username 改为 ip 创建一个接口 UserInfo2Mapper ,然后在接口中声明该方法 package com.example.mybatisdemo.mapper; import com.example.mybatisdemo.model.UserInfo; import org.apache.ibatis.annotations.*; import jav…...

Ubuntu18.04在线镜像仓库配置
在线镜像仓库 1、查操作系统版本 rootubuntu:~# lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.5 LTS Release: 18.04 Codename: bionic 2、原文件备份 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak 3、查…...
多数据源配置H2 Mysql
H2->Mysql数据迁移 需求背景环境说明实现过程配置调整原配置修改配置 代码调整新增DatasourceConfig配置类使用secondaryJdbcTemplate 需求背景 最近有一需求,原本项目中由于某些原因使用嵌入式数据库H2,鉴于嵌入式数据库可靠性以及不方便管理等因素…...
【ASP.NET Core 基础知识】--路由和请求处理--路由概念(一)
在Web应用中,路由是一个至关重要的概念,它负责将用户的请求映射到相应的处理程序,以确保正确的页面或资源被呈现给用户。通过将用户请求与适当的处理程序关联起来,使得应用能够以有序和可维护的方式响应用户的操作。 一、ASP.NET…...
【Unity】RayMarching体积云理论学习
RayMarching 体积云 RayMarching 是一种处理体积物体的方法 RayMarching 体积云的制作是基于屏幕后处理 屏幕空间重建世界坐标 目的是把屏幕坐标的每一个像素点转化成Unity世界坐标,可以得到射线的方向 如何在需要渲染的物体或者场景中使用RayMarchingÿ…...

物联网与智慧城市的无界未来:如何打破传统束缚,开启智能生活新篇章
目录 一、物联网:连接万物的技术革命 1、物联网的发展历程 2、物联网的核心技术 二、智慧城市:未来城市的蓝图与挑战 1、智慧城市的蓝图 2、智慧城市建设面临的挑战 3、应对挑战的措施 三、物联网与智慧城市的融合:打破传统束缚&…...

nodejs下载安装
一、node下载安装 官网下载 官网 根据自己电脑系统选择合适的版本进行下载,我这里选择window 64 位 下载完点击安装 打开cmd查看安装 此处说明下:新版的Node.js已自带npm,安装Node.js时会一起安装,npm的作用就是对Node.js…...
从零学Java - Lambda表达式
Lambda 表达式 文章目录 Lambda 表达式什么是 Lambda 表达式?怎么使用?1 基本语法:2 箭头符号:3 代码演示:4 注意事项 函数式接口1 什么是函数式接口2 常见函数式接口 方法引用(了解)1 什么是方法引用 什么是 Lambda 表达式? Lambda表达式:特殊的匿名内部类&…...

RV1103与FPGA通过MIPI CSI-2实现视频传输,实现网络推流
RV1103与FPGA通过MIPI CSI-2实现视频传输,实现网络推流。 一:图像格式 支持图像格式如下: [0]: NV16 (Y/CbCr 4:2:2) Size: Stepwise 64x64 - 2304x1296 with step 8/8 [1]: NV61 (Y/CrCb 4:2:2) Size: Stepwise 64x64 - 2304x1296 with …...

力扣62. 不同路径
动态规划 思路: 定义 dp[r][c] 为到达坐标 (r, c) 的路径数: 它只能有同一行左边相邻方格向右到达或者同一列上方相邻方格向下到达;状态转移方程: dp[r][c] dp[r][c - 1] dp[r - 1][c]初始状态 dp[0][0] 1第一行的路径数是 1第…...
使用Element-Plus 加载style
vue-chrome-extension 简介 chrome扩展开发插件基于vue3、ts、Element Plus、Webpack5、axios、less开发 支持content快速调用chrome对象及axios 详看 pages/content/app.vue 开箱即用chrome插件 特性 基础框架:使用 Vue3/Element PlusTypeScript: 应用程序级 J…...

Kafka常见指令及监控程序介绍
kafka在流数据、IO削峰上非常有用,以下对于这款程序,做一些常见指令介绍。 下文使用–bootstrap-server 10.0.0.102:9092,10.0.0.103:9092,10.0.0.104:9092 需自行填写各自对应的集群IP和kafka的端口。 该写法 等同 –bootstrap-server localhost:9092 …...

Docker 仓库管理
Docker 仓库管理 仓库(Repository)是集中存放镜像的地方。以下介绍一下 Docker Hub。当然不止 docker hub,只是远程的服务商不一样,操作都是一样的。 Docker Hub 目前 Docker 官方维护了一个公共仓库 Docker Hub。 大部分需求…...
LeetCode-410.分割数组的最大值
原题链接:https://leetcode.cn/problems/split-array-largest-sum/description 题面 给定一个非负整数数组 nums 和一个整数 k ,你需要将这个数组分成 k 个非空的连续子数组。设计一个算法使得这 k 个子数组各自和的最大值最小。 思路 数组定义ÿ…...
Redis和RediSearch的安装及使用
1. 安装要求 ReadiSearch要求Redis的版本在6.0以上RediSearch 要求使用 GNU Make 4.0 或更高版本 2. Redis的安装 查看redis的版本: redis-server --version或者,如果你已经启动了Redis服务器,你也可以使用redis-cli工具来获取版本信息&a…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...

AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...