MoonSharp 文档五

目录

13.Coroutines(协程)

Lua中的协程

从CLR代码中的协程

从CLR代码中的协程作为CLR迭代器

注意事项

抢占式协程

14.Hardwire descriptors(硬编码描述符)

为什么需要“硬编码”

什么是“硬编码”

如何进行硬编码

硬编码的优缺点

硬编码是实现IL2CPP、AOT或iOS兼容性的必要条件吗?

术语表

15.Sandboxing(沙盒)

为什么需要沙盒化

沙盒化检查清单

移除“危险”的 API

16.Tips and tricks for Unity3D(Unity3D的提示和技巧)

支持的平台

其他建议

使用更显式的构造函数之一初始化脚本加载器

17.FAQ / Recipes

如何重定向打印函数的输出?

如何将输入重定向到Lua程序?

如何重定向Lua程序的IO流?

如何限制脚本在不丢失状态的情况下执行的指令数?


MoonSharp 文档一-CSDN博客

MoonSharp 文档二-CSDN博客

MoonSharp 文档三-CSDN博客

MoonSharp 文档四-CSDN博客

13.Coroutines(协程)

来自 C# 和 Lua。

文档地址:MoonSharp

Lua中的协程

Lua 中的协程是开箱即用的支持。实际上,只要你不故意排除协程模块(参见沙盒化),它们就可以免费使用。有很多注意事项(这些也偶然适用于原始的 Lua 实现),并在下面的 “注意事项” 部分进行了讨论。

使用任何 Lua 协程教程来操作它们。

从CLR代码中的协程

协程可以通过脚本 CreateCoroutine 方法创建,该方法接受一个必须是函数的 DynValue。

string code = @"return function()local x = 0while true dox = x + 1coroutine.yield(x)endend";// Load the code and get the returned function
Script script = new Script();
DynValue function = script.DoString(code);// Create the coroutine in C#
DynValue coroutine = script.CreateCoroutine(function);// Resume the coroutine forever and ever..
while (true)
{DynValue x = coroutine.Coroutine.Resume();Console.WriteLine("{0}", x);
}

从CLR代码中的协程作为CLR迭代器

可以像调用迭代器一样调用协程:

string code = @"return function()local x = 0while true dox = x + 1coroutine.yield(x)if (x > 5) thenreturn 7endendend";// Load the code and get the returned function
Script script = new Script();
DynValue function = script.DoString(code);// Create the coroutine in C#
DynValue coroutine = script.CreateCoroutine(function);// Loop the coroutine 
string ret = "";foreach (DynValue x in coroutine.Coroutine.AsTypedEnumerable())
{ret = ret + x.ToString();
}Assert.AreEqual("1234567", ret);

注意事项

现在我们来到了协程相关内容中最重要的部分。就像在原始的 Lua 中一样,无法从嵌套调用中执行 yield 操作。

特别是在 MoonSharp 中,如果你在从 Lua 调用的 C# 函数中调用一个脚本,你不能使用 yield 来恢复到 C# 调用外部的协程。

不过有一个解决办法:返回一个 TailCallRequest 类型的 DynValue

return DynValue.NewTailCallReq(luafunction, arg1, arg2...); 

还可以指定一个 continuation(延续)——这是一段函数,它将在尾调用执行完成后被调用。

在 99% 的情况下,这可能是过度设计——甚至在大多数情况下,Lua 标准库也无法正确处理回调与 yield 的结合。但如果你计划自己实现像 `load`、`pcall` 或 `coroutine.resume` 这样的 API,这就是必需的。

另外,在某些边缘情况下,MoonSharp 处理 yield 的方式与标准 Lua 不同(在我尝试过的所有情况中,MoonSharp 的方式都更好,但谁知道呢)。例如,`tostring()` 支持在调用 `__tostring` 元方法时执行 yield 操作,而不会引发错误。

抢占式协程

在 MoonSharp 中,即使协程没有调用 `coroutine.yield`,也可以将其挂起。例如,如果想要非破坏性地限制脚本占用的 CPU 时间,这可能会很有用。但为了保持脚本的一致性,有一些需要注意的地方。

让我们从一个例子开始:

string code = @"function fib(n)if (n == 0 or n == 1) thenreturn 1;elsereturn fib(n - 1) + fib(n - 2);endend";// Load the code and get the returned function
Script script = new Script(CoreModules.None);
script.DoString(code);// get the function
DynValue function = script.Globals.Get("fib");// Create the coroutine in C#
DynValue coroutine = script.CreateCoroutine(function);// Set the automatic yield counter every 10 instructions. 
// 10 is likely too small! Use a much bigger value in your code to avoid interrupting too often!
coroutine.Coroutine.AutoYieldCounter = 10;int cycles = 0;
DynValue result = null;// Cycle until we get that the coroutine has returned something useful and not an automatic yield..
for (result = coroutine.Coroutine.Resume(8); result.Type == DataType.YieldRequest;result = coroutine.Coroutine.Resume()) 
{cycles += 1;
}// Check the values of the operation
Assert.AreEqual(DataType.Number, result.Type);
Assert.AreEqual(34, result.Number);

步骤如下:

1. 创建一个协程 

2. 将 `AutoYieldCounter` 设置为一个大于 0 的数字。1000 是一个不错的起点,可以根据需要调整。这个数字表示在执行多少条指令后,协程会主动挂起并返回给调用者。  

3. 调用 `coroutine.Coroutine.Resume(...)` 并传入适当的参数。

4. 如果上述调用的返回类型是 `DataType.YieldRequest`,则不带参数调用 `coroutine.Coroutine.Resume()`。 

5. 重复上一步,直到返回一个真正的结果类型。 

6. 完成。  

注意事项:

1. 如果代码重新进入(例如,`string.gsub` 的回调函数),在返回到“可挂起状态”之前,它不会被抢占。

2. 将标准协程操作与抢占式操作混合使用是可能的,但危险且复杂。请记住,协程可以在任何地方被抢占式挂起,因此无法保证操作的原子性等。如果混合使用,请务必小心。

14.Hardwire descriptors(硬编码描述符

自2016年以来帮助 AOT 和 IL2CPP

文档地址:MoonSharp

如果您不知道本页中使用的某些术语,请参阅底部的术语表部分。

为什么需要“硬编码”

MoonSharp 像大多数类库一样,使用反射,有时还会在运行时生成代码,以便从 Lua 脚本中访问 C# 代码。

从根本上说,MoonSharp 已经比大多数其他脚本引擎更加温和,原因在于:

理论上,它可以在完全不使用反射的情况下运行(尽管需要编写大量代码),这有助于提高速度并避免一些麻烦(如 IL2CPP 的 link.xml 问题)。
它不会在不应该生成IL代码的平台上生成IL代码(如 Xamarin 的 iOS、Unity 的 IL2CPP 平台等)。
前一点不会导致功能损失,只是速度会稍微慢一些。
这些都是优点,并且带来了很大的兼容性,但还可以做得更多。

如果大部分反射都被移除(剩下的少量反射也无害),并且还能获得更好的性能,那会怎样?

听起来好得不像真的?从某种意义上说,是的。这就是“硬编码”的用武之地,但需要付出一些代价。

什么是“硬编码”

这个想法很简单。为了避免反射,目前唯一的方法是编写大量的 C# 胶水代码。非常多。而且是难以编写的 C# 代码。但这并不是必须的——我们可以稍微简化一下编写方式。但这仍然是一项枯燥的工作,而且很容易出错。

然而,事实证明,这种枯燥、困难且容易出错的工作正是自动化的理想场景。而 MoonSharp 拥有完成这项工作所需的所有信息。

所以,简而言之,通过“硬编码”,MoonSharp 可以生成一堆不需要进一步反射类型就能运行的 C# 代码。

如何进行硬编码

很简单。嗯,几乎很简单。

MoonSharp 需要将已注册的所有类型的信息导出到某个地方。为此,需要编写一小段临时代码:

Table dump = UserData.GetDescriptionOfRegisteredTypes(true);
File.WriteAllText(@"c:\temp\testdump.lua", dump.Serialize());

重要的是,上述代码必须在所有类型都已注册之后运行。因此,硬编码的第一条规则是确保所有注册的顺序正确。

现在,可以使用 MoonSharp 的 REPL 解释器生成代码:

moonsharp -W c:\temp\testdump.lua c:\temp\out.cs --internals --class:MyClass --namespace:MyNamespace

此时,生成过程可能会输出大量警告/错误。它们会显示在控制台输出中,并作为代码中的注释。即使存在警告/错误,生成的代码仍然可以工作,但请花时间阅读这些警告/错误,因为如果你的脚本代码引用了触发这些警告/错误的成员,行为可能会与预期不同。

如果你没有 Windows 电脑,你可以轻松地使用 Mono 在 Mac 或 Linux 上运行 MoonSharp 解释器!

生成的代码将包含一个单一的公共静态类,其中有一个公共的静态 `Initialize` 方法,你应该在使用 MoonSharp 进行任何其他操作之前调用这个方法。非常简单。

如果你注册了一个系统类型(例如,数组),在硬编码时可能会遇到一些问题。原因是硬编码将使用生成 “dump” 时运行时的类型定义,如果你更改了 .NET 版本或平台,运行时可能会有所不同。虽然这看起来像是一个边缘情况,但在 Unity 的 Windows Phone 和 Windows Store 应用中会发生这种情况。在最坏的情况下,可以在生成的代码周围加上条件编译指令。

硬编码的优缺点

优点:

•  大幅减少反射的使用
•  在元数据被剥离的情况下(如IL2CPP),无需白名单类型
•  无需运行时代码生成
•  显著提升性能,尤其是在不支持运行时代码生成的平台上

缺点:

•  需要在工作流程中加入代码生成步骤
•  代码生成仅支持 C# 或 VB.NET
•  暴露的类型和成员必须对其他类可访问——简而言之,必须是`public`的,或者在同一程序集中为`internal`
•  某些类型的成员可能不受支持(例如事件,至少在当前版本中)  
•  值类型的设置器可能无法正常工作——或者比平时更糟,尽量避免使用它们
•  硬编码系统目前涵盖了所有通过 `UserDataType` 注册的类型,而不传递用户数据描述符。除了自定义描述符(显然需要你自己处理)之外,这意味着与 `PropertyTableAssigner` 和扩展方法一起使用的类型不包括在内。通常这问题不大,因为它们往往用于 IL2CPP 启发式算法可见的类型,未来可能会实现支持。

硬编码是实现IL2CPP、AOT或iOS兼容性的必要条件吗?

AOT 兼容性通过 `PlatformAccessor` 管理。实际上,唯一的行为变化是在 AOT 平台上不执行运行时代码生成,而是使用纯反射。

对于 IL2CPP 兼容性,硬编码简化了这一过程——通过消除为不应剥离的元数据维护 `link.xml` 文件的需求——并使其更高效,因为反射速度较慢。但你仍然可以通过向 `link.xml` 添加条目来实现兼容性。

术语表

反射(Reflection):  
一组允许代码“检查”自身并最终调用方法、读取和写入字段及属性等的类型和方法。虽然功能强大,但速度较慢。详见 MSDN 文档。

运行时代码生成(Runtime code generation):  
在运行时生成代码以优化通过反射完成的操作的做法。MoonSharp 在某些地方使用了这一技术,但在 AOT 平台上会被禁用。

IL(Intermediate Language,中间语言):  
.NET/mono 程序集中的代码以 IL(中间语言字节码)形式存储。这种字节码不能直接执行,必须在执行前转换为本地指令。

JIT(Just-In-Time,即时编译):  
通常,当 .NET 或 mono 加载程序集时,它们会对IL代码进行即时编译,将其转换为本地代码。这也可能在程序集的生命周期后期发生——例如,如果泛型类型的某个类型参数是值类型,通常会即时重新编译。

AOT(Ahead-of-Time,预先编译):  
mono 提供的一种选项(某种程度上 ngen 和 .NET Native 也提供,但与此讨论无关,至少目前如此),可以提前将代码编译为本地代码或其他形式。这并不简单,可能无法编译所有需要的代码。例如,如果使用反射来实例化代码中从未引用的类型,则该特定代码可能未被编译。在 iOS 设备上运行需要 AOT 执行。

IL2CPP:  
一种将 IL 转换为 C++ 源代码的出色软件。它是那种极难编写但大多数人谈论它时只是为了抱怨的软件。说真的,它试图解决的问题非常复杂,需要一些合作来确保兼容性。特别是,除了所有 AOT 问题(IL2CPP 必须使用 AOT)外,IL2CPP 还会对程序集元数据进行选择性剥离,这可能会干扰反射。在 Unity3D 下,IL2CPP 是 iOS、tvOS 和 WebGL 的强制要求,并在更多平台上作为选项提供。

link.xml:  
一个告诉 IL2CPP 应保留哪些类型的元数据的文件。

值类型(Value-type):  
值类型是按值传递而不是按引用传递的类型。它包括数值基元类型、枚举和结构体。当谈论值类型问题时,通常指的是结构体。详见 MSDN 上的结构体文档。最佳实践建议值类型应为不可变的,即它们的字段和属性应为只读的,如果需要更改它们,应创建一个新对象(对于结构体来说,这非常廉价)。MoonSharp 与可变结构体的兼容性不佳,因为它们是一种与许多事物都不兼容的奇怪存在,因此请不要使用它们。如果必须使用,请考虑使用代理对象进行变通。

15.Sandboxing(沙盒)

限制 Lua 脚本的功能

文档地址:MoonSharp

为什么需要沙盒化

沙盒化很可能是你使用 MoonSharp 时的关键功能。除非你以某种方式控制脚本提供者(可能还包括用户),否则在运行时加载脚本(或任何类型的代码,有时甚至是数据)时存在一个基本的信任问题:安全性。

例如,假设你正在编写一款视频游戏,并使用 Lua 使游戏“可修改”。用户可以访问某个社区网站并下载包含新关卡、AI等的模组,这些模组都使用 MoonSharp 编写以实现最大灵活性。大家都很开心。现在想象一下,如果某个恶意用户上传了一些隐藏在漂亮关卡中的恶意脚本,会发生什么……比如一个在桌面上创建 .exe 文件的脚本,其他用户可能会不小心点击它。

除非你信任用户,或者明显可以防止恶意使用,否则你不想向普通用户公开某些 API(如`os`、`io`和`file`)。

沙盒化检查清单

这份清单可以帮助你入门,但并不全面。

1. 确保脚本无法访问所有“危险”的标准 API。这肯定包括`io`、`os`和`file`,但根据你的脚本和偏执程度,可能还包括更多。请参阅下一章,了解如何轻松地使整个API集不可访问。

2. 不要使用 `InteropRegistrationPolicy.Automatic`。永远不要。

3. 检查你是否向脚本暴露了不应暴露的类型或类型成员。避免直接暴露你不拥有的类型,如 .NET 框架类型或 Unity 类型。如果需要,请参阅关于“代理对象”的部分,以及如何使用 `MoonSharpHide` 和 `MoonSharpHidden`。

4. 如果你希望脚本的某些部分访问这些危险的 API,请将它们放在单独的 `Script` 对象中,并确保其他脚本无法访问这些对象。

5. 如果绝对必须仅对脚本的一部分进行“沙盒化”,请参考这份经典指南。

移除“危险”的 API

移除危险 API 的最简单方法是使用接受 `CoreModules` 枚举的 `Script` 构造函数。

`CoreModules` 枚举的含义非常直观:

/// <summary>
/// Enumeration (combinable as flags) of all the standard library modules
/// </summary>
[Flags]
public enum CoreModules
{/// <summary>/// Value used to specify no modules to be loaded (equals 0)./// </summary>None = 0,/// <summary>/// The basic methods. Includes "assert", "collectgarbage", "error", "print", "select", "type", "tonumber" and "tostring"./// </summary>Basic = 0x40,/// <summary>/// The global constants: "_G", "_VERSION" and "_MOONSHARP"./// </summary>GlobalConsts = 0x1,/// <summary>/// The table iterators: "next", "ipairs" and "pairs"./// </summary>TableIterators = 0x2,/// <summary>/// The metatable methods : "setmetatable", "getmetatable", "rawset", "rawget", "rawequal" and "rawlen"./// </summary>Metatables = 0x4,/// <summary>/// The string package/// </summary>String = 0x8,/// <summary>/// The load methods: "load", "loadsafe", "loadfile", "loadfilesafe", "dofile" and "require"/// </summary>LoadMethods = 0x10,/// <summary>/// The table package /// </summary>Table = 0x20,/// <summary>/// The error handling methods: "pcall" and "xpcall"/// </summary>ErrorHandling = 0x80,/// <summary>/// The math package/// </summary>Math = 0x100,/// <summary>/// The coroutine package/// </summary>Coroutine = 0x200,/// <summary>/// The bit32 package/// </summary>Bit32 = 0x400,/// <summary>/// The time methods of the "os" package: "clock", "difftime", "date" and "time"/// </summary>OS_Time = 0x800,/// <summary>/// The methods of "os" package excluding those listed for OS_Time. These are not supported under Unity./// </summary>OS_System = 0x1000,/// <summary>/// The methods of "io" and "file" packages. These are not supported under Unity./// </summary>IO = 0x2000,/// <summary>/// The "debug" package (it has limited support)/// </summary>Debug = 0x4000,/// <summary>/// The "dynamic" package (introduced by MoonSharp)./// </summary>Dynamic = 0x8000,/// <summary>/// A sort of "hard" sandbox preset, including string, math, table, bit32 packages, constants and table iterators./// </summary>Preset_HardSandbox = GlobalConsts | TableIterators | String | Table | Basic | Math | Bit32,/// <summary>/// A softer sandbox preset, adding metatables support, error handling, coroutine, time functions and dynamic evaluations./// </summary>Preset_SoftSandbox = Preset_HardSandbox | Metatables | ErrorHandling | Coroutine | OS_Time | Dynamic,/// <summary>/// The default preset. Includes everything except "debug" as now./// Beware that using this preset allows scripts unlimited access to the system./// </summary>Preset_Default = Preset_SoftSandbox | LoadMethods | OS_System | IO,/// <summary>/// The complete package./// Beware that using this preset allows scripts unlimited access to the system./// </summary>Preset_Complete = Preset_Default | Debug,}

16.Tips and tricks for Unity3D(Unity3D的提示和技巧)

为在 Unity 上使用 MoonSharp 的用户提供的快速提示集

文档地址:MoonSharp

支持的平台

一般来说,MoonSharp 的目标是支持所有平台。然而,在 Unity 中测试 MoonSharp 在所有平台上的表现是非常困难的,几乎是不可能的。

因此,平台被分为不同的等级。

1.预计完全支持独立的 Windows、Linux 和 OS/X * 安卓 * iOS * tvOS

2.预计零星支持,将在可能的情况下测试小问题/不支持的功能 WebGL * Windows 应用商店应用程序 Windows Phone

3.应该有效,但我很难提供支持其他层没有的东西

4.不支持,您只能自己使用目前尚不清楚,将进行更新以防

其他建议

•  如果可能,不要暴露 Unity 类型  
•  尽可能使用代理对象  
•  在运行于 IL2CPP 和/或 AOT 平台之前,使用硬编码  
•  如果可能,永远不要暴露结构体  

使用更显式的构造函数之一初始化脚本加载器

使用 UnityAssetsScriptLoader 的显式构造函数来注册所有脚本文件。通过在项目的最开始使用这个小片段,您不需要将 Unity 自带的库添加到 link.xml 中,就可以在 IL2CPP 平台上运行。

示例:

Dictionary<string, string> scripts = new  Dictionary<string, string>();object[] result = Resources.LoadAll("Lua", typeof(TextAsset));foreach(TextAsset ta in result.OfType<TextAsset>()){scripts.Add(ta.name, ta.text);}Script.DefaultOptions.ScriptLoader = new MoonSharp.Interpreter.Loaders.UnityAssetsScriptLoader(scripts);

17.FAQ / Recipes

常见问题的简单示例

文档地址:MoonSharp

如何重定向打印函数的输出?

script.Options.DebugPrint = s => { Console.WriteLine(s); }

如何将输入重定向到Lua程序?

script.Options.DebugInput = () => { return Console.ReadLine(); }

如何重定向Lua程序的IO流?

IoModule.SetDefaultFile(script, Platforms.StandardFileType.StdIn, myInputStream);
IoModule.SetDefaultFile(script, Platforms.StandardFileType.StdOut, myOutputStream);
IoModule.SetDefaultFile(script, Platforms.StandardFileType.StdErr, myErrorStream);

如何限制脚本在不丢失状态的情况下执行的指令数?

参考 Preemptive coroutines.

end

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nginx + Keepalived 高可用集群

一、NginxKeepalived 原理 1.1.Nginx 负载均衡机制 Nginx 是一款轻量级且高性能的 Web 服务器和反向代理服务器&#xff0c;在负载均衡方面有着卓越的表现。其具备强大的七层流量管理能力&#xff0c;能够基于 URL、Cookie、HTTP 头信息等对请求进行精准路由。例如&#xff0…

面试提问(1)

面试提问 1.你能说一说C/C之间的区别吗&#xff1f;2.你能将一些你对构造函数和析构函数的认识吗&#xff1f;3.讲一下继承和多态4.你了解TCP/IP四层网络模型吗&#xff1f;5.你了解三次握手和四次挥手吗&#xff1f;6.讲一下进程和线程&#xff1f;7.你对二叉树的了解有哪些&a…

Adobe Genuine Service Alert 一直弹窗,老是一直弹窗【解决方法】

在使用Adobe系列软件时&#xff0c;若没有正版授权&#xff0c;则会出现弹窗&#xff0c;该弹窗是由Adobe Genuine Service软件弹出的&#xff0c;且该弹窗无法关闭&#xff0c;下文介绍如何永久关闭该弹窗。 方法一&#xff1a; 首先在任务栏鼠标右键打开任务管理器&#xff…

防汛应急包,快速响应,守护安全

根据中国水利部统计&#xff0c;自1949年以来&#xff0c;我国几乎每年都面临洪水威胁&#xff0c;其中20世纪90年代后洪涝灾害频率显著增加&#xff0c;仅1990-2009年间就发生超4000起较大灾害&#xff0c;直接经济损失近3万亿元&#xff0c;受灾人口达20亿人次。在2020年长江…

一文了解JVM的垃圾回收

Java堆内存结构 java堆内存是垃圾回收器管理的主要区域&#xff0c;也被称为GC堆。 为了方便垃圾回收&#xff0c;堆内存被分为新生代、老年代和永久代。 新创建的对象的内存会在新生代中分配&#xff0c;达到一定存活时长后会移入老年代&#xff0c;而永久代存储的是类的元数…

【人工智能 | 大数据】基于人工智能的大数据分析方法

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈智能大数据分析 ⌋ ⌋ ⌋ 智能大数据分析是指利用先进的技术和算法对大规模数据进行深入分析和挖掘&#xff0c;以提取有价值的信息和洞察。它结合了大数据技术、人工智能&#xff08;AI&#xff09;、机器学习&#xff08;ML&a…

【C语言】编译和链接详解

hi&#xff0c;各位&#xff0c;让我们开启今日份博客~ 小编个人主页点这里~ 目录 一、翻译环境和运行环境1、翻译环境1.1预处理&#xff08;预编译&#xff09;1.2编译1.2.1词法分析1.2.2语法分析1.2.3语义分析 1.3汇编1.4链接 2.运行环境 一、翻译环境和运行环境 在ANSI C…

在Simulink中将Excel数据导入可变负载模块的方法介绍

文章目录 数据准备与格式要求Excel数据格式MATLAB预处理数据导入方法使用From Spreadsheet模块(直接导入Excel)通过MATLAB工作区中转(From Workspace模块)使用1-D Lookup Table模块(非线性负载映射)Signal Builder模块(变载工况导入)可变负载模块配置注意事项与调试在S…

Java 大视界 -- Java 大数据在智慧文旅虚拟导游与个性化推荐中的应用(130)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

【微知】tmux如何在一个会话的1个窗口中水平分割或者垂直分割窗口?(垂直 Ctrl + b, %; 切换Ctrl + b, 方向键; ctrl d关闭)

背景 除了直接创建窗口&#xff0c;还可以分割一个窗口。创建窗口参考兄弟篇&#xff1a;tmux如何在某个会话session中创建多个窗口&#xff1f;如何切换&#xff1f;&#xff08;Ctrlb c创建&#xff1b;Ctrlb 数字 切换&#xff1b;Ctrlb &关闭&#xff09; 命令 垂…

强化学习(赵世钰版)-学习笔记(7.时序差分学习)

本章是课程算法与方法中的第四章&#xff0c;介绍的时序差分学习算法是基于随机近似方法设计的强化学习方法&#xff0c;也是model-free的方法。 时序差分算法是一种近似估计策略状态值的算法&#xff0c;具体的形式如下&#xff1a; 本质上是在当前t时刻&#xff0c;被访问到的…

无公网IP也能远程控制Windows:Linux rdesktop内网穿透实战

文章目录 前言1. Windows 开启远程桌面2. Linux安装rdesktop工具3. Win安装Cpolar工具4. 配置远程桌面地址5. 远程桌面连接测试6. 设置固定远程地址7. 固定地址连接测试 前言 如今远程办公已经从一种选择变成了许多企业和个人的必修课&#xff0c;而如何在Linux系统上高效地访…

深度学习与大模型-矩阵

矩阵其实在我们的生活中也有很多应用&#xff0c;只是我们没注意罢了。 1. 矩阵是什么&#xff1f; 简单来说&#xff0c;矩阵就是一个长方形的数字表格。比如你有一个2行3列的矩阵&#xff0c;可以写成这样&#xff1a; 这个矩阵有2行3列&#xff0c;每个数字都有一个位置&a…

【实战ES】实战 Elasticsearch:快速上手与深度实践-8.2.1AWS OpenSearch无服务器方案

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 8.2.1AWS OpenSearch 无服务器方案深度解析与实践指南1. Serverless架构的核心价值与行业趋势1.1 传统Elasticsearch集群的运维挑战1.2 Serverless技术演进路线技术特性对比…

使用 Arduino 和 ESP8266 Wi-Fi 模块发送电子邮件

使用 Arduino Uno 和 ESP8266 Wi-Fi 模块发送电子邮件 我们正在迈向物联网 (IoT) 世界。这项技术在电子和嵌入式系统中起着非常重要的作用。从任何微控制器或嵌入式系统发送电子邮件都是非常基本的事情,这在 IoT 中是必需的。因此,在本文中,我们将学习“如何使用 Wi-Fi 和…

jmeter-AES加密

AES(全称&#xff1a;Advanced Encryption Standard)对称加密算法&#xff0c;也就是加密和解密用到的密钥是相同的&#xff0c;这种加密方式加密速度非常快&#xff0c; 适合经常发送数据的场合&#xff0c;如&#xff1a;数据加密存储、网络通信加密等。 在进行接口测试或接…

四种 No-SQL

在一个常规的互联网服务中&#xff0c;读取与写入的比例大约是 100:1 到 1000:1。然而&#xff0c;从硬盘读取时&#xff0c;数据库连接操作耗时&#xff0c;99% 的时间花费在磁盘寻址上。 为了优化读取性能&#xff0c;非规范化的设计通过添加冗余数据或分组数据来引入。下述…

使用 Chrome Flags 设置(适用于 HTTP 站点开发)

使用 Chrome Flags 设置&#xff08;适用于 HTTP 站点开发&#xff09; 在 Chrome 地址栏输入&#xff1a;chrome://flags/在搜索框输入 “Insecure origins” 或 “Allow invalid certificates”。找到 “Insecure origins treated as secure” 选项&#xff08;或者 #allow-…

openharmony体验

openharmony5 去年已经出来了 如果以前做过android开发的&#xff0c;学起来不难&#xff0c;关键 1&#xff1a;环境 DevEco Studio 5.0.3 Beta2 https://developer.huawei.com/consumer/cn/deveco-studio/ win10_64bit CPU amd64(不是arm的) 2:安装 执行EXE 安装就行&#x…

【微知】plantuml在泳道图中如何将多个泳道框起来分组并且设置颜色?(box “浏览器“ #LightGreen endbox)

泳道分组并且着色 分组用 box和endbox &#xff0c;颜色用#xxx&#xff0c;标注用"xxx" box "浏览器" #LightGreen participant "浏览器1" as Browser participant "浏览器2" as Browser2 endboxparticipant "服务端" as …