seL4 IPC(五)

news2024/12/24 2:31:13

官网链接:link

求解

代码中的很多方法例如这一个教程里面的seL4_GetMR(0),我在官方给的手册和API中都搜不到,想问一下大家这些大家都是在哪里搜的!!

IPC

seL4中的IPC和一般OS中讲的IPC概念相差比较大,根据官方的意思是理解seL4的IPC的时候,最好忘记IPC的概念,起这个名字只是为了标准上对齐,但是理解的时候最好将其当作专有名词来理解。

背景知识

进程间通信(IPC)是用于在进程之间同步传输少量数据和能力的微内核机制。在seL4中,称为端点的小型内核对象促成了IPC,端点充当的是通讯的端口。端点对象的调用通常被用于收发IPC数据。
端点们由一系列的等待收发信息的线程组成。为了理解这一点,思考一个案例:n个线程正在一个端点上等待一个信息。如果n个端点在一个端点上发送信息,那么n个在该端点上等待信息的线程都将会收到这些信息且被唤醒。如果此时有第n+1个发送者发送一个信息,那么这个发送者将会排队等待。

系统调用

线程可以通过系统调用seL4_Send在端点上发送信息,一直阻塞到信息被其他线程接收的时候seL4_NBSend也可以用,它执行轮询发送:该发送仅当已经有一个线程阻塞等待一个信息的时候才会发送成功,否则就失败。为了避免出现反向通道,seL4_NBSend不返回指示消息是否已发送的结果。
seL4_Recv 可用于接收消息,seL4_NBRecv 可用于轮询消息。
seL4_Call是一个系统调用,本质上结合了seL4_Send和seL4_Recv,但是有一个主要区别:在接收阶段,使用此函数的线程被阻塞在一个一次性能力上,称为回复能力(reply capability),而不是在端点本身上。在client-server场景下,客户端使用seL4_Call发出请求,服务器可以显式的回复正确的客户端。
回复能力(reply capability)内部存储在接收者的线程控制块(TCB)中。系统调用 seL4_Reply 会调用这个能力,向客户端发送一个进程间通信(IPC)并将其唤醒。seL4_ReplyRecv 也执行相同操作,但它在一个组合的系统调用中发送回复并阻塞在提供的端点上。
由于线程控制块(TCB)只有一个空间来存储回复能力(reply capability),如果服务器需要处理多个请求(例如在硬件操作完成后再进行回复),可以使用 seL4_CNode_SaveCaller 将回复能力保存到接收者的 CSpace 中的一个空槽中。

方法说明
seL4_Send发送后阻塞,直到对方接收之后才会取消阻塞
seL4_NBSend非阻塞发送,发送后继续往下执行,但不告知发送结果,防止反向通道
seL4_Call立即发送,阻塞等待回复,该回复不是说对方发消息的回复,而是使用seL4_Reply进行回复,才会取消阻塞继续往下执行
seL4_Reply响应的功能,只有他能唤醒call调用的阻塞,也可唤醒seL4_Recv的阻塞
seL4_Recv阻塞等待,直到有消息到达,这个消息可以是回复(Send、NBSend),也可以是响应Reply

反向通道 (back channel)

back channel(反向通道) 指的是一种非预期的或隐藏的信息传递路径,可能会导致信息泄露或安全问题。通常,在操作系统或安全系统中,设计者希望确保通信通道只能按照预期的方式工作,防止信息通过其他途径(即“反向通道”)泄露。在 seL4_NBSend 的情况下,如果系统返回了消息是否成功发送的结果,发送者就能通过这个结果推断接收者的状态(例如,接收者是否正在等待消息)。这就可能成为一个反向通道,允许一个线程获取另一个线程的状态信息,而这类信息可能会被滥用。因此,seL4_NBSend 不返回结果来避免这种潜在的安全隐患。

IPC Buffer

每个线程都有一个Buffer(被称之为IPC Buffer),它包含IPC消息,是由数据和能力组成的。发送发指定消息长度,内核在发送方和接收放IPC缓冲区之间复制此(有界)长度。

Data transfer

IPC 缓冲区包含用于在 IPC 上传输数据的消息寄存器 (MR) 有界区域。每个寄存器都是机器字大小,最大消息大小可在 libsel4 提供的 seL4_MsgMaxLength 常量中找到。
可以使用seL4_SetMR 将消息加载到IPC 缓冲区中,并使用seL4_GetMR 提取消息小消息在寄存器中发送,不需要复制操作。适合寄存器的字数可在 seL4_FastMessageRegisters 常量中获得。
所传输的数据量(根据所使用的消息寄存器的数量)必须设置为 seL4_MessageInfo_t 数据结构中的长度字段。

消息寄存器和IPC缓冲区之间的关系

1、消息寄存器

  • 消息寄存器是 seL4 内核用于短消息传递的一个内部概念。在 seL4 中,系统为每个线程分配了一些虚拟寄存器,用于存储发送和接收的消息数据。这些消息寄存器主要用于传递少量数据(例如几字节到几百字节)。在处理简单的 IPC 传递时,寄存器用来保存消息内容。
  • seL4_GetMR(index) 函数的作用就是访问某个消息寄存器中的数据。index 代表消息寄存器的索引号,比如 0 代表第一个消息寄存器。

2、IPC buffer

  • IPC buffer 是 seL4 中的一个内存区域,用于消息传递。当消息过大、超出了消息寄存器的容量时,IPC buffer 才被使用。IPC buffer 位于线程控制块 (TCB) 中,线程可以通过这个缓冲区来传递大消息或能力等复杂的数据结构。
  • 也就是说,小消息存储在消息寄存器中,而大消息存储在 IPC buffer 中。

3、二者之间的关系

  • 当 seL4 处理 IPC 消息时,它首先会使用消息寄存器来传递较小的消息(这比访问内存中的 IPC buffer 更快)。
  • 如果消息的大小超过了消息寄存器的容量,系统会将它分片后存入 IPC buffer,寄存器中只保存与此消息相关的元数据或控制信息

Cap transfer

除了数据之外,IPC 还可用于在每个消息的进程之间发送能力。这称为能力转移。正在传输的能力数量在 seL4_MessageInfo_t 结构中编码为 extraCaps。下面是通过 IPC 发送能力的示例:

seL4_MessageInfo info = seL4_MessageInfo_new(0, 0, 1, 0);
seL4_SetCap(0, free_slot);
seL4_Call(endpoint, info);

在这里插入图片描述
以前是玩过单片机,看到这个寄存器的时候十分敏感,总觉得是硬件寄存器。此处的寄存器指的是IPC消息的能力槽位(capability slot)中。所以上面的seL4_SetCap(0, free_slot) 的作用是把free_slot这个能力放到IPC消息info的第一个能力槽位中(槽位索引为0)。
若想要接收能力,接收者必须指定一个 cspace 地址来放置该能力。这如下面的代码示例所示:

seL4_SetCapReceivePath(cnode, badged_endpoint, seL4_WordBits);
seL4_Recv(endpoint, &sender);

接收到的能力的访问权限与接收者对端点拥有的权限相同。请注意,虽然发送方可以发送多种功能,但接收方一次只能接收一种功能。

Capability unwrapping 能力解包

在进程间通信(IPC)中,seL4 也可以对能力(capability)进行解包(unwrapping)。如果消息中的第 n 个能力引用了用于发送消息的端点(endpoint),那么该能力会被解包:它的徽章(badge)会被放置在接收者的 IPC 缓冲区的第 n 个位置(在 caps_or_badges 字段中),同时内核会将 seL4_MessageInfo_t 中 capsUnwrapped 字段的第 n 位(从最低有效位开始计数)设置为 1。
解释一下:
在 seL4 系统中,能力(capability)是线程访问系统资源(例如端点、内存等)的权限。在 IPC 通信中,发送方可以通过消息传递这些能力给接收方。解包(unwrapping) 是指内核自动将发送方传递的能力标识符从能力对象中提取出来,并放置在接收方的 IPC 缓冲区中,供接收方使用。
具体来说,如果消息中第 n 个能力引用了用于发送消息的端点(指的是在 IPC 消息中,第 n 个能力是与消息发送的那个端点相关联的能力。换句话说,这个能力能够访问发送消息的端点或者与其进行交互。),那么 seL4 会对这个能力进行特殊处理:它会提取出这个能力的 badge(徽章),并将其放在接收方的 IPC 缓冲区中相应的位置。同时,内核会通过设置 capsUnwrapped 字段中的位来标记哪些能力被解包了。

Message Info

seL4_MessageInfo_t 数据结构用于将 IPC 消息的描述编码为单个字。它用于描述要发送到seL4的消息,并让seL4描述发送到接收者的消息。它包含以下字段:

  • length :消息中消息寄存器(数据)的数量(seL4_MsgMaxLength 最大值)
  • extraCaps :消息中的能力数量 (seL4_MsgMaxExtraCaps)
  • capsUnwrapped :标记被内核解包的能力
  • label :从发送方传输到接收方的未经内核修改的数据

Badges 徽章

除了消息,内核还会传递发送者调用以发送消息的端点能力的徽章(badge)。端点可以通过 seL4_CNode_Mint 或 seL4_CNode_Mutate 来进行标记。一旦端点被徽章标记,接收到该端点消息的任何接收者都会获得该端点的徽章。下面的代码示例演示了这一点:

seL4_Word badge;
seL4_Recv(endpoint, &badge);
// once a message is received, the badge value is set by seL4 to the
// badge of capability used by the sender to send the message

Fastpath

快速 IPC 对于基于微内核的系统至关重要,因为服务通常彼此分离以进行隔离,而 IPC 是客户端和服务之间通信的核心机制之一。因此,IPC 有一个快速路径——内核中经过高度优化的路径——它允许这些操作非常快。为了使用快速路径,IPC 必须满足以下条件:

  • 必须使用seL4_Call或seL4_ReplyRecv
  • 消息中的数据必须适合 seL4_FastMessageRegisters 寄存器。
  • 进程必须具有有效的地址空间
  • 不传送能力
  • 调度程序中没有比被 IPC 解除阻塞的线程优先级更高的其他线程可以运行。

额,还是想吐槽,太复杂了

实操

这篇教程中有几个由capDL loader设置好的进程,两个clients一个server。所有进程都拥有对同一个端点能力访问的权限,该能力提供了对同一个端点对象的访问。看了上面的背景知识仍然不是很能搞懂,下面插一节补充。

补充

  • IPC 缓冲区:每个线程(TCB)都有自己专属的 IPC 缓冲区,用于发送和接收消息。这个缓冲区通常是在线程的用户地址空间内,通过 seL4_SetIPCBuffer 设置。在执行 IPC 操作时,内核会自动将消息放入该线程的 IPC 缓冲区
  • 端点(endpoint):端点是 seL4 中用于线程之间通信的对象。多个线程可以共享同一个端点能力,这意味着它们可以通过这个端点进行通信。例如,两个线程可以都向同一个端点发送或接收消息,从而实现消息的交换或同步

在对端点的解释中,说向同一个端点发送或接收消息,这句话令人很摸不着头脑,下面基于五个对象(线程A、线程B、端点A、线程A的IPC缓冲区、线程B的IPC缓冲区)举一个IPC通信的完整例子,辅助理解。
场景

线程A需要向线程B发送一个消息。线程A和线程B通过端点A来实现通信。每个线程都有自己的IPC缓冲区来存储消息。

对象

  • 线程A:发送消息的线程。
  • 线程B:接收消息的线程。
  • 端点A:线程A 和线程B 用于通信的共享端点。
  • 线程A的IPC缓冲区:用于存储线程A发送或接收的消息内容。
  • 线程B的IPC缓冲区:用于存储线程B接收的消息内容。

IPC流程

  1. 创建端点A: 系统中创建一个端点对象 端点A,它用来作为通信通道,供线程A 和线程B 通过它进行消息的传递。两者共享这个端点。
  2. 线程A向端点A发送消息:线程A 将消息放入自己的 IPC缓冲区,并使用系统调用 seL4_Send(endpointA) 来发送消息。这个系统调用会将消息从 线程A的IPC缓冲区 发送到 端点A。端点A 在这个时候相当于一个“信箱”,等待另一个线程(线程B)来取消息。
  3. 线程B等待接收消息:线程B 通过调用 seL4_Recv(endpointA) 在 端点A 上等待消息。这时,线程B 阻塞(等待消息到达)。当消息到达时,内核会通过端点讲消息从线程A的IPC缓冲区 拷贝到 线程B的IPC缓冲区
  4. 消息传递完成:当消息被传递到 线程B的IPC缓冲区 后,线程B 不再阻塞,恢复运行,并可以从它的 IPC 缓冲区读取消息。

流程如下:

线程A的IPC缓冲区 ---> 端点A ---> 线程B的IPC缓冲区

上面的流程给人一种端点A存储了通信的信息的感觉,实际上端点A本身并不存储消息。但是它实际上是一个同步机制,用于协调消息在不同线程之间的传递。在seL4中,消息通过IPC机制在不同线程之间传递,端点A起的是“连接”作用,而不是数据存储作用。

IPC的工作机制

  • 线程A 调用 seL4_Send(endpointA) 发送消息时,消息被存储在线程A的IPC缓冲区中
  • 线程B 调用 seL4_Recv(endpointA) 接收消息时,内核会将消息从 线程A的IPC缓冲区 复制到 线程B的IPC缓冲区,通过端点A作为中介来协调消息的传递。
    也就是说,端点A起到的是协调消息传递的作用,它不存储数据,而是促使内核将数据从发送者的缓冲区拷贝到接收者的缓冲区。

所以端点的作用是什么?

  • 内核通过它判断哪些线程在等待消息或发送消息。
  • 当线程B准备好接收消息时,内核会在后台完成消息从 线程A的IPC缓冲区 到 线程B的IPC缓冲区 的数据拷贝
  • 端点A 是一个信号机制,用于确定消息何时可以被传递。它不存储消息,也没有持有对线程A IPC缓冲区的访问权限。

回到教程

在这篇教程中,你将会创建一个服务器,输出由客户端发送过来的信息内容。你还讲更改客户端回复的顺序以获得正确的消息。当你运行代码的时候,输出差不多是这样子的(输出的顺序可能不太一样):
在这里插入图片描述
在初始化时,两个客户端使用以下协议:它们在提供的端点上等待通过能力转移发送给它们的带徽章的端点。之后,客户端发送的所有消息都使用带徽章的端点,以便服务器能够识别客户端。然而,服务器当前并没有发送带徽章的能力!我们提供了代码来给端点能力加徽章,并回复客户端。
练习:我们的任务是设置能力传送,这样客户端才能成功的接收到带徽章的端点(能力)。看一下代码:

seL4_Word badge = seL4_GetMR(0);//这个函数用于从当前线程的消息寄存器中读取指定索引位置的值。索引从 0 开始,因此 seL4_GetMR(0) 返回的是第一个消息寄存器的值。

// server在自己的地址空间复制了一个带徽章的端点能力,下面需要做的是将这个能力传给发送者(看完下面方法的详解就能看懂这个方法是干啥的了)
seL4_Error error = seL4_CNode_Mint(cnode, free_slot, seL4_WordBits,
                                   cnode, endpoint, seL4_WordBits,
                                   seL4_AllRights, badge);
printf("Badged %lu\n", badge);

// TODO use cap transfer to send the badged cap in the reply 将这个徽章标记的端点能力发出去

/* reply to the sender and wait for the next message */
seL4_Reply(info);

/* now delete the transferred cap */
error = seL4_CNode_Delete(cnode, free_slot, seL4_WordBits);
assert(error == seL4_NoError);

/* wait for the next message */
info = seL4_Recv(endpoint, &sender);

看一下seL4_CNode_Mint这个方法,其作用是拷贝一个能力,同时设置其权限和徽章。
在这里插入图片描述
现在我们来梳理一下一个server和两个client的逻辑。

对于server.c而言

  1. 在初始的时候会调用seL4_Recv阻塞住自己,等待client发送信息过来,在之前我们说过,这个阻塞只要对方有消息过来就会被唤醒
  2. 当有消息过来了之后,进入一个死循环,以下是死循环的内容
  3. 判断有没有badge。
  4. 如果没有badge,则取收到的消息第一个寄存器的内容作为badge,复制一个带badge的endpoint,将能力放在free_slot插槽里面,创建一个IPC消息体,使用reply传回这个消息体,然后删除掉新创建的能力,然后阻塞等待下一条消息(进行下一次循环,回到3)
  5. 如果有badge,暂时是空的(指的是原代码,里面的内容需要我们填充),回到3

对于client.c而言(两个client的逻辑完全相同,只挑一个说)

  1. 设置好收到的能力放置在哪个槽里面
  2. 第一个消息寄存器中填入值
  3. 创建一个IPC消息体,使用call发送出去,然后阻塞等待reply
  4. 等到了reply之后,将定义在数组中的单词,放置在消息寄存器中发出去,然后阻塞等待回复,直到所有的单词发完为止

上面理清楚了之后做第一个TODO

// TODO use cap transfer to send the badged cap in the reply
// 只发送一个能力
info = seL4_MessageInfo_new(0, 0, 1, 0);
// 消息体的能力槽中指定要传送的能力
seL4_SetCap(0,free_slot);

运行之后输出如下:
在这里插入图片描述
运行到这里的时候,两个client都会因为call的调用而阻塞住,而server端因为运行到了else里面,是空的,所以我们需要继续填充else中的内容。
进行下一个TODO:

// TODO use printf to print out the message sent by the client
seL4_Word length = seL4_MessageInfo_get_length(info);//seL4_MessageInfo_get_length这个方法是我搜出来的
for (int i = 0; i <= length; i++)
{
  seL4_Word character = seL4_GetMR(i);  // 获取每个消息寄存器中的字符
  printf("%c", (char)character);   // 将其作为字符打印
}
// followed by a new line
printf("\n");  // 打印换行符

输出如下:
在这里插入图片描述
做下一个TODO:

// TODO reply to the client and wait for the next message
//  info = seL4_MessageInfo_new(0, 0, 0, 0);
seL4_Reply(info);
info = seL4_Recv(endpoint, &sender);

输出如下:
在这里插入图片描述
不知道为啥报错。 有知道的请留言,seL4_CNode_SaveCaller这个没用,谁用了请留言,交流一下。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华大基因用药指导基因检测助力优化治疗方案,科学管理糖尿病

糖尿病是全球范围内的一个重大公共卫生问题。据国际糖尿病联盟&#xff08;IDF&#xff09;统计&#xff0c;全球糖尿病患者人数约为5.39亿&#xff0c;其中中国患者数量约为1.409亿。作为一种慢性代谢性疾病&#xff0c;糖尿病往往不是独立存在的&#xff0c;通常还会伴随着多…

【SSM_Day3】JSON字符串和Java对象互转

【SSM_Day3】JSON字符串和Java对象互转 JSON档案JSON字符串和Java对象互转BEJSON&#xff1a;在线JSON格式化校验工具 JSON档案 数据格式是描述数据保存在文件或记录中的规则&#xff0c;比如Excel就是一种数据格式&#xff0c;数据保存在Excel的表格中。JSON也是一种数据格式…

【JAVA报错已解决】Java.lang.NumberFormatException

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

Python:百度贴吧实现自动化签到

早知道&#xff0c;还是python。 Github项目仓库在这。 相关API 签到贴吧列表 签到分为两个接口&#xff0c;PC端签到一次经验2&#xff0c;而移动端签到则是一次经验6。该用哪个接口已经很明显了。不过这里还是列出PC端的签到API。 # PC端签到接口 # sign_url "https:…

Hive SQL业务场景:连续5天涨幅超过5%股票

一、需求描述 现有一张股票价格表 dwd_stock_trade_dtl 有3个字段分别是&#xff1a; 股票代码(stock_code), 日期(trade_date)&#xff0c; 收盘价格(closing_price) 。 请找出满足连续5天以上&#xff08;含&#xff09;每天上涨超过5%的股票&#xff0c;并给出连续满足…

LLM大模型书籍:专补大模型短板的RAG入门与实战书来了!

文末赠书 RAG自2020年由Facebook AI Research推出后&#xff0c;一下子就窜红了。 毕竟&#xff0c;它是真的帮了大忙&#xff0c;在解决大语言模型的“幻觉”问题上起到了关键作用。 如今&#xff0c;Google、AWS、IBM、微软、NVIDIA等科技巨头都在支持RAG应用的开发。微软…

AGI interior designer丨OPENAIGC开发者大赛高校组AI创作力奖

在第二届拯救者杯OPENAIGC开发者大赛中&#xff0c;涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到&#xff0c;我们特意开设了优秀作品报道专栏&#xff0c;旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者&#xff0c;希望能带给…

同步、异步、阻塞、非阻塞的关系

相关介绍 1、同步与异步&#xff1a;针对调用方而言。调用方是否需要等待返回调用结果。异步不需要等待&#xff0c;可以采用状态通知、回调函数的方式获取结果&#xff0c;以read文件为例 同步方式读取文件&#xff1a;read(filename)&#xff0c;直接读取文件&#xff0c;需…

【C语言训练题库】第一次出现的字符

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 1. 题目 给出一串字符串&#xff0c;找出第一次只出现一次的字符&#xff0c;并返回它的位置&#xff0c;如果不存在&#xff0c;则返回-1 例&#xff1a; 输入&…

电缆缺陷检测系统源码分享

电缆缺陷检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

Llama3的本地部署

Llama3是Meta于2024年4月18日开源的LLM&#xff0c;目前开放了8B和70B两个版本&#xff0c;两个版本均支持最大为8192个token的序列长度( GPT-4支持128K ) Llama3在Meta自制的两个24K GPU集群上进行预训练&#xff0c;使用15T的训练数据&#xff0c;其中5%为非英文数据&…

SAP 用户密码策略设置简介(不需要重启服务器)

SAP 用户密码策略设置简介(不需要重启服务器 1. 密码长度和复杂性2. 密码有效期3. 密码历史记录4. 账户锁定5. 单点登录&#xff08;SSO&#xff09;6. 安全提示和教育7. 配置密码策略的步骤8. 监控和审计 业务场景系统设置 好的&#xff0c;这里是关于SAP用户密码策略的更详细…

7.字符串 Strings

作业系统链接 字符串文字可以使用单引号、双引号或三引号来定义&#xff0c;其中三引号特别适用于多行字符串。转义序列如\n&#xff08;换行&#xff09;和\t&#xff08;制表符&#xff09;在字符串中起到特殊作用。字符串方法如replace()、strip()、lower()和upper()提供了丰…

「漏洞复现」誉龙视音频综合管理平台 RelMedia/FindById SQL注入漏洞

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

基于RepLKNet31B模型在RML201610a数据集上的调制识别【代码+数据集+python环境+GUI系统】

基于RepLKNet31B模型在RML201610a数据集上的调制识别【代码数据集python环境GUI系统】 Loss曲线 背景意义 随着社会的快速发展&#xff0c;人们在通信方面的需求逐渐增加&#xff0c;特别是在无线通信领域。通信环境的复杂化催生了多种通信形式和相关应用&#xff0c;这使得调…

【Java】类型转换 —— 自动转换、强制转换与表达式类型自动提升

1&#xff0e;自动类型转换 Java中的自动类型转换就好比将小瓶水倒入到大瓶的换装过程。我们将小瓶水倒入到大瓶中时&#xff0c;由于小瓶的容量比大瓶的容量小&#xff0c;所以倒入的水永远不可能溢出大瓶。同样&#xff0c;在Java中&#xff0c;将取值范围小的数据类型的变量…

T8:猫狗识别

T8周&#xff1a;猫狗识别 **一、前期工作**1.设置GPU,导入库2.导入数据3.查看数据 **二、数据预处理**1.加载数据2.可视化数据3.配置数据集 **三、构建CNN网络模型****四、编译模型****五、训练模型****六、模型评估****七、预测**八、总结1、[train_on_batch 和 test_on_batc…

得物App荣获国家级大奖,以沉浸式体验重塑消费新标杆

近日&#xff0c;备受瞩目的中国国际服务贸易交易会&#xff08;简称“服贸会”&#xff09;在北京举行。得物App作为上海科技企业代表参展&#xff0c;向全球展现中国企业的数字化创新服务。在展台现场&#xff0c;得物App搭建了首个3D创新应用“球鞋博物馆”&#xff0c;对球…

探探Java与python中的闭包

说在前面&#xff1a;在计算机科学中&#xff0c;闭包是指一个函数以及其引用的周围环境&#xff08;变量&#xff09;所组成的整体。简单来说&#xff0c;闭包允许一个函数访问并操作其外部函数作用域中的变量&#xff0c;即使外部函数已经执行完毕。 Java函数式编程—闭包&am…

828华为云征文|华为云Flexus云服务器X实例之openEuler系统下搭建MaxKB开源知识库问答系统

828华为云征文&#xff5c;华为云Flexus云服务器X实例之openEuler系统下搭建MaxKB开源知识库问答系统 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、MaxKB 介绍2.1 MaxKB简介2.2 MaxKB整体架构…