当前位置: 首页 > news >正文

【SGX系列教程】(二)第一个 SGX 程序: HelloWorld,linux下运行

文章目录

  • 0. SGX基础原理分析
  • 一.准备工作
    • 1.1 前提条件
    • 1.2 SGX IDE
    • 1.3 基本原理
  • 二.程序设计
    • 2.1 目录结构
    • 2.2 源码设计
      • 2.2.1 Encalve/Enclave.edl:Enclave Description Language
      • 2.2.2 Enclave/Enclave.lds: Enclave linker script
      • 2.2.3 Enclave/Enclave.config.xml: Enclave 配置文件,如堆栈大小、是否支持 Debug 等
      • 2.2.4 Enclave/Enclave.h
      • 2.2.5 Enclave/Enclave.cpp
      • 2.2.6 Enclave/Enclave_private.pem:enclave.so 的签名私钥
      • 2.2.7 App/App.h
      • 2.2.8 App/App.cpp
    • 2.3 Makefile
    • 2.4 编译 & 运行
    • 2.5 总结
  • 三.参考链接
  • 四. 感谢支持

0. SGX基础原理分析

    本文将向大家展示如何基于 Intel SGX SDK 开发一个最简单 SGX 应用:HelloWorld,这个程序在可信区生产 "Hello world"并传递给不可信代码(缓冲区)打印输出到终端。 虽然 Intel SGX SDK 安装目录中默认提供了数个 Sample,但每个 Sample 对于初学者来说非常复杂和难以理解。 我们先快速上手,然后再逐个分析每个Sample。关于 SGX 开发运行环境的搭建可参考之前的一篇博客:【SGX系列教程】(一)。

    为了更深刻理解理解SGX工程上运行原理,我们先对SGX原理做介绍:

1. 开发者眼中SGX长什么样子?

在这里插入图片描述
    简单来说SGX就是提供了一个安全内存及其相关。下面稍微讲一下SGX软件栈结构(具体见《SGX软件栈》文档)。

    总的来说,SGX是划分两个世界的——可信世界和不可信世界。每一个世界中,想要使用SGX的开发都需要开发哪一个世界的代码,一般来说,不可信世界开发非敏感代码(称为APP,另一种理解就是APP也包含Enclave,这样为了区分,就把不可信的叫做APP),可信世界开发敏感代码(Enclave),或者说敏感代码移入了可信世界。

    既然有了两个世界,他们之间的连接就需要有一个叫做桥函数的东西,ECALL桥能让APP可以调用桥函数间接调用Enclave中写好的API函数。反向的有个叫OCALL桥的东西。桥函数上承载着两个世界间传递的参数,而且ECALL中,Enclave并不信任APP传给Enclave的ECALL参数,所以需要参数的消毒检查。OCALL有点类似。

    既然要开发程序,就要用到SDK(我这里是把可信Enclave使用的SDK称为SDK,这也符合Intel的叫法,另一种理解是SDK包括给不可信APP使用的PSW、给可信Enclave使用的SDK、桥函数)和PSW,这两个都是Intel提供的(linux下见: github.com/intel/linux-sgx)。由于Enclave要保证自己内部开发的函数尽可能不会离开Enclave,所以Enclave内部用的SDK都是用静态库链接,除非万不得已,比如系统调用等,那么就得同OCALL桥到不可信世界完成任务。然后顶多是启发式的对OCALL返回值进行检查(而且目前Intel并无消毒检查,除非Enclave开发者自己做检查)。

    PSW、SDK一部分功能是用于我们传统的那种为了具有某个功能而开发的函数,还有一部分是对CPU提供的SGX功能指令的包装,主要用于SGX特性的支持,为了让你真正和CPU沟通,并获得SGX特性支持。SGX特性是通过CPU向外面提供Ring0指令和Ring3指令,其中Ring0指令ENCLS主要有一些比如创建Enclave这种生命周期管理、页权限管理的指令。Ring3指令ENCLU主要是让控制流能够在两个世界之间流动,比如进出Enclave这种。这一块的细节可以看《SGX软件栈》。

2. SGX访问控制是什么?

    SGX访问控制是说对Enclave安全内存进行访问控制,不能让攻击者非法访问敏感内存。这主要还是通过CPU内部实现的。有SGX特性CPU能够让不可信APP只有满足进入它的Enclave的条件时才能放行,而且Enclave A和Enclave B之间是互相不可访问的。这种逻辑是CPU里面的EPCM和内存RAM中被CPU定义为EPC里面的SECS结构体、TCS结构体这些单元连动完成的。《SGX技术的分析和研究》有介绍具体有哪几则访问控制。

3. CPU里面SGX长什么样子?

在这里插入图片描述
在这里插入图片描述
4. SGX内存分配方式?
在这里插入图片描述

一.准备工作

1.1 前提条件

    [必须] 你的开发环境必须安装了 Intel SGX SDK。在安装时安装到了 /opt/intel/sgxsdk

    [可选] 开发环境主机 CPU 支持 SGX;若不支持,可采用模拟器编译运行(本文实际在硬件支持条件下测试)。

1.2 SGX IDE

    本文在ubuntu22.04中执行,主要是参考了Sample中工程代码的组织方法。

1.3 基本原理

在这里插入图片描述
    在演示代码之前,有必要先了解下 SGX 程序最基本的原理:

  • SGX应用由两部分组成:
    1. untrusted 不可信区:代码和数据运行在普通非加密内存区域,程序 main 入口必须在非可信区;上图中的 main() 和 bar() 函数均在非可信区。
    2. truested 可信区:代码和数据运行在硬件加密内存区域,此区域由 CPU 创建的且只有CPU有权限访问; 上图中的 helloworld() 和 foo() 函数运行在可信区。

  • 非可信区只能通过 ECALL 函数调用可信区内的函数。

  • 可信区只能通过 OCALL 函数调用非可信区的函数。

  • ECALL 函数和 OCALL 函数通过 EDL 文件声明。

二.程序设计

    第一个SGX 程序: HelloWorld

2.1 目录结构

HelloWorld/
├── App
│   ├── App.cpp
│   └── App.h
├── Enclave
│   ├── Enclave.config.xml
│   ├── Enclave.cpp
│   ├── Enclave.edl
│   ├── Enclave.h
│   ├── Enclave.lds
│   └── Enclave_private.pem
├── Include
└── Makefile

上面目录结构仿照了 sgxsdk/SampleCode 目录下示例代码目录:

App 目录内为不可信区域代码,包括 main 入口、OCALL 函数内具体逻辑代码等等。
Enclave 目录为可信区域代码,包括 ECALL 函数内具体逻辑代码实现。

  • Enclave.edl: EDL(Enclave Description Language)文件。
  • Enclave.lds: Enclave linker script。
  • Enclave_private.pem: enclave.so 的签名私钥
  • Enclave.config.xml: Enclave 配置文件,如堆栈大小、是否支持 Debug 等。
  • Enclave.h & Enclave.cpp: 应用安全区代码实现。

Include 目录是不可信代码和可信代码共享的头文件。

2.2 源码设计

2.2.1 Encalve/Enclave.edl:Enclave Description Language

enclave {trusted {public void ecall_hello_from_enclave([out, size=len] char* buf, size_t len);};
};
  • EDL 中声明了一个公共 ECALL 函数,每个 SGX 应用的 EDL 必须至少声明一个 public 类型的 ECALL 函数。
  • trusted {...}内声明 ECALL 函数, untrusted {...} 内申明 OCALL 函数,由于本例中安全区不需要向非安全区调用(OCALL),所以只声明了一个 ECALL 函数 ecall_hello_from_enclave,这个 ECALL 函数目的是在安全区创建一个 Buffer 并填充 "Hello world",然后这个 Buffer 的内容拷贝到非安全的 Buffer 中,非安全区调用 printf 打印这个非安全 Buffer 内容。

2.2.2 Enclave/Enclave.lds: Enclave linker script

enclave.so
{global:g_global_data_sim;g_global_data;enclave_entry;g_peak_heap_used;local:*;
};

2.2.3 Enclave/Enclave.config.xml: Enclave 配置文件,如堆栈大小、是否支持 Debug 等

<EnclaveConfiguration><ProdID>0</ProdID><ISVSVN>0</ISVSVN><StackMaxSize>0x40000</StackMaxSize><HeapMaxSize>0x100000</HeapMaxSize><TCSNum>10</TCSNum><TCSPolicy>1</TCSPolicy><!-- Recommend changing 'DisableDebug' to 1 to make the enclave undebuggable for enclave release --><DisableDebug>0</DisableDebug><MiscSelect>0</MiscSelect><MiscMask>0xFFFFFFFF</MiscMask>
</EnclaveConfiguration>

这个配置文件是用来定义Intel SGX信任域(Enclave)的各种参数的。下面是对每一行代码的详细分析,包括它们的功能和用途:

  • <EnclaveConfiguration> 开始标签:表示SGX信任域配置文件的开始。
  • <ProdID>0</ProdID>ProdID:表示产品ID。这个值可以由开发者定义,用于区分不同的产品版本。在这里,它被设置为0,表示默认产品ID。
  • <ISVSVN>0</ISVSVN>ISVSVN:表示独立软件供应商(ISV)的安全版本号。这个值由ISV管理,用于跟踪代码的安全更新。这里设置为0,表示初始的安全版本。
  • <StackMaxSize>0x40000</StackMaxSize>StackMaxSize:堆栈的最大大小,以十六进制表示。这里设置为0x40000(262144字节或256KB),表示信任域的堆栈内存上限为256KB
  • <HeapMaxSize>0x100000</HeapMaxSize>HeapMaxSize:堆的最大大小,以十六进制表示。这里设置为0x100000(1048576字节或1MB),表示信任域的堆内存上限为1MB
  • <TCSNum>10</TCSNum>TCSNum:线程控制结构(TCS)的数量。这里设置为10,表示可以有10个并发线程在信任域中运行。
  • <TCSPolicy>1</TCSPolicy>TCSPolicy:TCS的策略。一般情况下,设置为1表示使用默认策略。
  • <DisableDebug>0</DisableDebug>DisableDebug:定义是否禁用调试。设置为0表示启用调试模式,方便开发调试。但建议在发布版本中设置为1,这样信任域将无法被调试,增强安全性。
  • <MiscSelect>0</MiscSelect>MiscSelect:选择Miscellaneous功能。这里设置为0,表示未选择任何特定的Misc功能。
  • <MiscMask>0xFFFFFFFF</MiscMask>MiscMask:定义可用Miscellaneous功能的掩码。0xFFFFFFFF表示允许所有Misc功能。
  • </EnclaveConfiguration>结束标签:表示SGX信任域配置文件的结束。

总的来说,这个配置文件定义了一个SGX信任域的各种参数和属性,包括产品ID、安全版本号、堆栈和堆内存大小、并发线程数量和策略、调试功能以及Misc功能掩码等。通过设置这些参数,开发者可以控制信任域的内存使用、并发控制以及调试属性,确保信任域在运行时具有所需的功能和安全性。

2.2.4 Enclave/Enclave.h

这个头文件内容基本为空的。

#ifndef _ENCLAVE_H_
#define _ENCLAVE_H_
#endif

2.2.5 Enclave/Enclave.cpp

#include "Enclave.h"
#include "Enclave_t.h" /* print_string */
#include <string.h>void ecall_hello_from_enclave(char *buf, size_t len)
{const char *hello = "Hello world";size_t size = len;if(strlen(hello) < len){size = strlen(hello) + 1;}memcpy(buf, hello, size - 1);buf[size-1] = '\0';
}

2.2.6 Enclave/Enclave_private.pem:enclave.so 的签名私钥

基于openssl命令生成私钥:

openssl genrsa -out Enclave/Enclave_private.pem -3 3072

2.2.7 App/App.h

#ifndef _APP_H_
#define _APP_H_#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>#include "sgx_error.h"       /* sgx_status_t */
#include "sgx_eid.h"     /* sgx_enclave_id_t */#ifndef TRUE
# define TRUE 1
#endif#ifndef FALSE
# define FALSE 0
#endif# define TOKEN_FILENAME   "enclave.token"
# define ENCLAVE_FILENAME "enclave.signed.so"extern sgx_enclave_id_t global_eid;    /* global enclave id */#if defined(__cplusplus)
extern "C" {
#endif#if defined(__cplusplus)
}
#endif#endif /* !_APP_H_ */

2.2.8 App/App.cpp

#include <stdio.h>
#include <string.h>
#include <assert.h># include <unistd.h>
# include <pwd.h>
# define MAX_PATH FILENAME_MAX#include "sgx_urts.h"
#include "App.h"
#include "Enclave_u.h"/* Global EID shared by multiple threads */
sgx_enclave_id_t global_eid = 0;int initialize_enclave(void)
{sgx_status_t ret = SGX_ERROR_UNEXPECTED;/* 调用 sgx_create_enclave 创建一个 Enclave 实例 *//* Debug Support: set 2nd parameter to 1 */ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, NULL, NULL, &global_eid, NULL);if (ret != SGX_SUCCESS) {printf("Failed to create enclave, ret code: %d\n", ret);return -1;}return 0;
}/* 应用程序入口 */
int SGX_CDECL main(int argc, char *argv[])
{(void)(argc);(void)(argv);const size_t max_buf_len = 100;char buffer[max_buf_len] = {0};/* 创建并初始化 Enclave */if(initialize_enclave() < 0){printf("Enter a character before exit ...\n");getchar();return -1;}/* ECALL 调用 */ecall_hello_from_enclave(global_eid, buffer, max_buf_len);printf("%s\n", buffer);/* 销毁 Enclave */sgx_destroy_enclave(global_eid);printf("Info: SampleEnclave successfully returned.\n");printf("Enter a character before exit ...\n");getchar();return 0;
}

2.3 Makefile

    随便在Sample中找一个工程中的Makefile,稍加改改就能用!!!

######## SGX SDK Settings ########
# 设置 SGX SDK 的路径、模式、架构和调试选项
# SGX SDK 安装路径
SGX_SDK ?= /opt/intel/sgxsdk
# SGX 模式:硬件模式(HW)
SGX_MODE ?= HW
# SGX 架构:64 位(x64)
SGX_ARCH ?= x64
# SGX 调试模式:启用(1)
SGX_DEBUG ?= 1# 判断系统的位数,如果是 32 位,设置架构为 x86
ifeq ($(shell getconf LONG_BIT), 32)SGX_ARCH := x86
# 如果编译器标志中包含 -m32,也设置架构为 x86
else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32)SGX_ARCH := x86
endif# 根据架构选择编译器标志、库路径和工具路径
ifeq ($(SGX_ARCH), x86)SGX_COMMON_FLAGS := -m32                         # 设置 32 位编译标志SGX_LIBRARY_PATH := $(SGX_SDK)/lib               # 32 位库路径SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign # 使用 32 位签名工具SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r     # 使用 32 位 Edger8r 工具
elseSGX_COMMON_FLAGS := -m64                         # 设置 64 位编译标志SGX_LIBRARY_PATH := $(SGX_SDK)/lib64             # 64 位库路径SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign # 使用 64 位签名工具SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r     # 使用 64 位 Edger8r 工具
endif# 检查是否同时设置了调试模式和预发布模式
ifeq ($(SGX_DEBUG), 1)
ifeq ($(SGX_PRERELEASE), 1)
$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!)
# 如果两个都设置了,报错 "不能同时设置调试模式和预发布模式"
endif
endif# 根据是否启用调试模式设置编译标志
ifeq ($(SGX_DEBUG), 1)SGX_COMMON_FLAGS += -O0 -g  # 调试模式:不进行优化,包含调试信息
elseSGX_COMMON_FLAGS += -O2    # 生产模式:优化代码
endif# 设置更多的编译器警告标志,确保代码质量
SGX_COMMON_FLAGS += -Wall -Wextra -Winit-self -Wpointer-arith -Wreturn-type \-Waddress -Wsequence-point -Wformat-security \-Wmissing-include-dirs -Wfloat-equal -Wundef -Wshadow \-Wcast-align -Wcast-qual -Wconversion -Wredundant-decls
SGX_COMMON_CFLAGS := $(SGX_COMMON_FLAGS) -Wjump-misses-init -Wstrict-prototypes -Wunsuffixed-float-constants # C 编译标志
SGX_COMMON_CXXFLAGS := $(SGX_COMMON_FLAGS) -Wnon-virtual-dtor -std=c++11  # C++ 编译标志,使用 C++11 标准######## App Settings ######### 应用程序设置
ifneq ($(SGX_MODE), HW)Urts_Library_Name := sgx_urts_sim  # 如果不是硬件模式,使用仿真库
elseUrts_Library_Name := sgx_urts      # 如果是硬件模式,使用真实库
endif# 指定应用程序的源文件和包含路径
App_Cpp_Files := App/App.cpp $(wildcard App/TrustedLibrary/*.cpp)
App_Include_Paths := -IApp -I$(SGX_SDK)/include# 设置应用程序的编译标志
App_C_Flags := -fPIC -Wno-attributes $(App_Include_Paths)# 根据不同的配置模式,设置不同的宏定义
# Three configuration modes - Debug, prerelease, release
#   Debug - Macro DEBUG enabled.
#   Prerelease - Macro NDEBUG and EDEBUG enabled.
#   Release - Macro NDEBUG enabled.
ifeq ($(SGX_DEBUG), 1)App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG
else ifeq ($(SGX_PRERELEASE), 1)App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG
elseApp_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG
endifApp_Cpp_Flags := $(App_C_Flags)
App_Link_Flags := -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread # 生成对象文件的规则
App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o)
# 指定生成的应用程序名称
App_Name := app######## Enclave Settings ########
# 设置信任域版本脚本文件根据调试模式与硬件模式判断
Enclave_Version_Script := Enclave/Enclave.lds
ifeq ($(SGX_MODE), HW)
ifneq ($(SGX_DEBUG), 1)
ifneq ($(SGX_PRERELEASE), 1)# 硬件发布模式下使用的版本脚本文件# Choose to use 'Enclave.lds' for HW release modeEnclave_Version_Script = Enclave/Enclave.lds 
endif
endif
endif# 仿真模式与硬件模式下使用不同的库
ifneq ($(SGX_MODE), HW)Trts_Library_Name := sgx_trts_sim      # 仿真模式库Service_Library_Name := sgx_tservice_sim # 仿真模式服务库
elseTrts_Library_Name := sgx_trts         # 硬件模式库Service_Library_Name := sgx_tservice  # 硬件模式服务库
endif
Crypto_Library_Name := sgx_tcrypto        # 加密库# 指定信任域的源文件和包含路径
Enclave_Cpp_Files := Enclave/Enclave.cpp $(wildcard Enclave/TrustedLibrary/*.cpp)
Enclave_Include_Paths := -IEnclave -I$(SGX_SDK)/include -I$(SGX_SDK)/include/libcxx -I$(SGX_SDK)/include/tlibc # 设置信任域的编译标志
Enclave_C_Flags := -nostdinc -fvisibility=hidden -fpie -fstack-protector -fno-builtin-printf $(Enclave_Include_Paths)
Enclave_Cpp_Flags := $(Enclave_C_Flags) -nostdinc++# 启用安全链接选项
Enclave_Security_Link_Flags := -Wl,-z,relro,-z,now,-z,noexecstack# 生成信任域的正确链接规则
# 按步骤链接信任库
Enclave_Link_Flags := $(Enclave_Security_Link_Flags) \-Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \-Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \-Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \-Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \-Wl,-pie,-eenclave_entry -Wl,--export-dynamic  \-Wl,--defsym,__ImageBase=0 \-Wl,--version-script=$(Enclave_Version_Script)
# 指定信任域生成的对象文件
Enclave_Cpp_Objects := $(Enclave_Cpp_Files:.cpp=.o)
# 指定生成的信任域库名
Enclave_Name := enclave.so
Signed_Enclave_Name := enclave.signed.so
# 配置文件和测试密钥文件
Enclave_Config_File := Enclave/Enclave.config.xml
Enclave_Key := Enclave/Enclave_private.pem# 生成不同的构建模式名称
ifeq ($(SGX_MODE), HW)
ifeq ($(SGX_DEBUG), 1)Build_Mode = HW_DEBUG
else ifeq ($(SGX_PRERELEASE), 1)Build_Mode = HW_PRERELEASE
elseBuild_Mode = HW_RELEASE
endif
else
ifeq ($(SGX_DEBUG), 1)Build_Mode = SIM_DEBUG
else ifeq ($(SGX_PRERELEASE), 1)Build_Mode = SIM_PRERELEASE
elseBuild_Mode = SIM_RELEASE
endif
endif.PHONY: all run target
all: .config_$(Build_Mode)_$(SGX_ARCH)@$(MAKE) targetifeq ($(Build_Mode), HW_RELEASE)
target: $(App_Name) $(Enclave_Name)@echo "The project has been built in release hardware mode."@echo "Please sign the $(Enclave_Name) first with your signing key before you run the $(App_Name) to launch and access the enclave."@echo "To sign the enclave use the command:"@echo "   $(SGX_ENCLAVE_SIGNER) sign -key <your key> -enclave $(Enclave_Name) -out <$(Signed_Enclave_Name)> -config $(Enclave_Config_File)"@echo "You can also sign the enclave using an external signing tool."@echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW."
else
target: $(App_Name) $(Signed_Enclave_Name)
ifeq ($(Build_Mode), HW_DEBUG)@echo "The project has been built in debug hardware mode."
else ifeq ($(Build_Mode), SIM_DEBUG)@echo "The project has been built in debug simulation mode."
else ifeq ($(Build_Mode), HW_PRERELEASE)@echo "The project has been built in pre-release hardware mode."
else ifeq ($(Build_Mode), SIM_PRERELEASE)@echo "The project has been built in pre-release simulation mode."
else@echo "The project has been built in release simulation mode."
endif
endif# 运行目标规则,首先构建所有目标,然后运行应用程序,除非是在硬件发布模式下。
run: all
ifneq ($(Build_Mode), HW_RELEASE)@$(CURDIR)/$(App_Name)@echo "RUN  =>  $(App_Name) [$(SGX_MODE)|$(SGX_ARCH), OK]"
endif# 配置文件生成规则,如果构建模式和架构改变,重新生成配置
.config_$(Build_Mode)_$(SGX_ARCH):@rm -f .config_* $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.*@touch .config_$(Build_Mode)_$(SGX_ARCH)######## App Objects ######### 生成 Enclave_u.h,如果 Enclave.edl 改变
App/Enclave_u.h: $(SGX_EDGER8R) Enclave/Enclave.edl@cd App && $(SGX_EDGER8R) --untrusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include@echo "GEN  =>  $@"App/Enclave_u.c: App/Enclave_u.h# 编译 Enclave_u.c 生成对象文件
App/Enclave_u.o: App/Enclave_u.c@$(CC) $(SGX_COMMON_CFLAGS) $(App_C_Flags) -c $< -o $@@echo "CC   <=  $<"# 编译应用程序源文件生成对象文件
App/%.o: App/%.cpp App/Enclave_u.h@$(CXX) $(SGX_COMMON_CXXFLAGS) $(App_Cpp_Flags) -c $< -o $@@echo "CXX  <=  $<"# 链接对象文件生成应用程序可执行文件
$(App_Name): App/Enclave_u.o $(App_Cpp_Objects)@$(CXX) $^ -o $@ $(App_Link_Flags)@echo "LINK =>  $@"######## Enclave Objects ########
# 生成 Enclave_t.h,如果 Enclave.edl 改变
Enclave/Enclave_t.h: $(SGX_EDGER8R) Enclave/Enclave.edl@cd Enclave && $(SGX_EDGER8R) --trusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include@echo "GEN  =>  $@"Enclave/Enclave_t.c: Enclave/Enclave_t.h# 编译 Enclave_t.c 生成对象文件
Enclave/Enclave_t.o: Enclave/Enclave_t.c@$(CC) $(SGX_COMMON_CFLAGS) $(Enclave_C_Flags) -c $< -o $@@echo "CC   <=  $<"# 编译信任域源文件生成对象文件
Enclave/%.o: Enclave/%.cpp@$(CXX) $(SGX_COMMON_CXXFLAGS) $(Enclave_Cpp_Flags) -c $< -o $@@echo "CXX  <=  $<"# 生成信任域对象文件
$(Enclave_Cpp_Objects): Enclave/Enclave_t.h# 链接对象文件生成信任域共享库文件
$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects)@$(CXX) $^ -o $@ $(Enclave_Link_Flags)@echo "LINK =>  $@"# 使用测试私钥签名信任域共享库文件
$(Signed_Enclave_Name): $(Enclave_Name)
ifeq ($(wildcard $(Enclave_Key)),)@echo "There is no enclave test key<Enclave_private_test.pem>."@echo "The project will generate a key<Enclave_private_test.pem> for test."@openssl genrsa -out $(Enclave_Key) -3 3072
endif@$(SGX_ENCLAVE_SIGNER) sign -key $(Enclave_Key) -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File)@echo "SIGN =>  $@"# clean 目标,删除生成的文件
.PHONY: cleanclean:@rm -f .config_* $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.*

2.4 编译 & 运行

    比较简单,直接在项目目录下执行 make,在项目根目录下会生成一个名为 app 的 Binary,运行这个 app:

$ make
make[1]: 进入目录“/home/hututu/myproject/sgx/helloworld”
GEN  =>  App/Enclave_u.h
CC   <=  App/Enclave_u.c
CXX  <=  App/App.cpp
LINK =>  app
GEN  =>  Enclave/Enclave_t.h
CC   <=  Enclave/Enclave_t.c
CXX  <=  Enclave/Enclave.cpp
LINK =>  enclave.so
<EnclaveConfiguration><ProdID>0</ProdID><ISVSVN>0</ISVSVN><StackMaxSize>0x40000</StackMaxSize><HeapMaxSize>0x100000</HeapMaxSize><TCSNum>10</TCSNum><TCSPolicy>1</TCSPolicy><!-- Recommend changing 'DisableDebug' to 1 to make the enclave undebuggable for enclave release --><DisableDebug>0</DisableDebug><MiscSelect>0</MiscSelect><MiscMask>0xFFFFFFFF</MiscMask>
</EnclaveConfiguration>
tcs_num 10, tcs_max_num 10, tcs_min_pool 1
INFO: Enclave configuration 'MiscSelect' and 'MiscSelectMask' will prevent enclave from using dynamic features. To use the dynamic features on SGX2 platform, suggest to set MiscMask[0]=0 and MiscSelect[0]=1.
The required memory is 3997696B.
The required memory is 0x3d0000, 3904 KB.
handle_compatible_metadata: Overwrite with metadata version 0x100000004
Succeed.
SIGN =>  enclave.signed.so
The project has been built in debug hardware mode.
make[1]: 离开目录“/home/hututu/myproject/sgx/helloworld”$ ./app
Hello world
Info: SampleEnclave successfully returned.
Enter a character before exit ...

编译基本流程(Makefile):

  1. 通过 sgx_edger8r 工具在 App/ 目录下生成不可信代码(Enclave_u.cEnclave_u.h),这部分生成代码主要会调用 ECALL (sgx_ecall)
  2. 编译不可信部分 Binary: app
  3. 通过sgx_edger8r 工具在 Enclave/ 目录下生成可信代码(Enclave_t.cEnclave_t.h);
  4. 编译可信动态链接库(enclave.so);
  5. 通过sgx_sing工具签名可信动态链接库(enclave.signed.so);
  6. 结束。

编译后的代码目录结构:

HelloWorld
├── app
├── App
│   ├── App.cpp
│   ├── App.h
│   ├── App.o        #[generated]
│   ├── Enclave_u.c  #[generated] 
│   ├── Enclave_u.h  #[generated] 
│   └── Enclave_u.o  #[generated]
├── Enclave
│   ├── Enclave.config.xml
│   ├── Enclave.cpp
│   ├── Enclave.edl
│   ├── Enclave.h
│   ├── Enclave.lds
│   ├── Enclave.o     #[generated]
│   ├── Enclave_private.pem
│   ├── Enclave_t.c   #[generated]
│   ├── Enclave_t.h   #[generated]
│   └── Enclave_t.o   #[generated]
├── enclave.signed.so #[generated]
├── enclave.so        #[generated]
├── Include
└── Makefile

2.5 总结

   即便最简单的 SGX HelloWold 也比较复杂,当然“安全性”和“成本”(技术壁垒门槛、开发成本、维护成本、物料成本等)总是成正比的,和“效率”成反比的。希望这篇文章对那些想入门开发 SGX 应用的用户有所帮助。

三.参考链接

https://developer.aliyun.com/article/740793
Intel SGX入门(一)——背景篇_sgx的psw是什么-CSDN博客

四. 感谢支持

    完结撒花!后续将持续输出,形成Intel SGX的系列教程,并结合密码学算法设计更复杂功能。希望看到这里的小伙伴能点个关注,也欢迎志同道合的小伙伴一起广泛交流。
    码字实属不易,如果本文对你有10分帮助,就赏个10分把,感谢各位大佬支持!

在这里插入图片描述

相关文章:

【SGX系列教程】(二)第一个 SGX 程序: HelloWorld,linux下运行

文章目录 0. SGX基础原理分析一.准备工作1.1 前提条件1.2 SGX IDE1.3 基本原理 二.程序设计2.1 目录结构2.2 源码设计2.2.1 Encalve/Enclave.edl:Enclave Description Language2.2.2 Enclave/Enclave.lds: Enclave linker script2.2.3 Enclave/Enclave.config.xml: Enclave 配置…...

网页报错dns_probe_possible 怎么办?——错误代码有效修复

当你在浏览网页时遇到dns_probe_possible 错误&#xff0c;这通常意味着你的浏览器无法解析域名系统&#xff08;DNS&#xff09;地址。这个问题可能是由多种原因引起的&#xff0c;包括网络配置问题、DNS服务问题、或是本地设备的问题。教大家几种修复网页报错dns_probe_possi…...

Vue.js 中属性绑定的详细解析:冒号 `:` 和非冒号的区别

Vue.js 中属性绑定的详细解析&#xff1a;冒号 : 和非冒号的区别 在 Vue.js 中&#xff0c;属性绑定是一个重要的概念&#xff0c;它决定了如何将数据绑定到 DOM 元素的属性上。Vue.js 提供了两种方式来绑定属性&#xff1a;使用冒号 : 进行动态绑定&#xff0c;或直接书写属性…...

使用Java实现智能物流管理系统

使用Java实现智能物流管理系统 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何使用Java语言实现智能物流管理系统&#xff0c;这是一个涉及到…...

深圳技术大学oj C : 生成r子集

Description 输出给定序列按字典序的 &#xfffd; 组合&#xff0c;按照所有 &#xfffd; 个元素出现与否的 01 标记串 &#xfffd;&#xfffd;&#xfffd;&#xfffd;−1,...,&#xfffd;1 的字典序输出. 此处01串的字典序指&#xff1a;先输入的数字对应低位&#x…...

不同操作系统下的换行符

1. 关键字2. 换行符的比较3. ASCII码4. 修改换行符 4.1. VSCode 5. 参考文档 1. 关键字 CR LF CRLF 换行符 2. 换行符的比较 英文全称英文缩写中文含义转义字符ASCII码值操作系统Carriage ReturnCR回车\r13MacIntosh&#xff08;早期的Mac&#xff09;LinefeedLF换行/新行\…...

Transformation(转换)开发-switch/case组件

一、switch/case组件-条件判断 体育老师要做一件非常重要的事情&#xff1a;判断学生是男孩还是女孩、或者是蜘蛛&#xff0c;然后让他们各自到指定的队伍中 体育老师做的事情&#xff0c;我们同样也会在Kettle中会经常用来。在Kettle中&#xff0c;switch/case组件可以来做类似…...

Android Gradle 开发与应用 (二): Android 项目结构与构建配置

目录 1. Android 项目的 Gradle 文件结构 1.1 项目根目录 1.2 模块目录 2. Gradle 构建配置详解 2.1 配置 Android 项目的 build.gradle 2.2 配置模块的 build.gradle 2.3 使用 productFlavors 管理多版本应用 2.4 使用 buildConfigField 注入构建常量 在 Android 开发…...

02:vim的使用和权限管控

vim的使用 1、vim基础使用1.1、vim pathname 2、vim高级用法2.1、查找2.2、设置显示行号2.3、快速切换行2.4、 行删除2.5、行复制粘贴 3、权限管理3.1、普通用户和特权用户3.2、文件权限表示 vim是Linux中的一种编辑器&#xff0c;类似于window中的记事本&#xff0c;可以对创建…...

GNeRF代码复现

https://github.com/quan-meng/gnerf 之前一直去复现这个代码总是文件不存在&#xff0c;我就懒得搞了&#xff08;实际上是没能力哈哈哈&#xff09; 最近突然想到这篇论文重新试试复现 一、按步骤创建虚拟环境安装各种依赖等 二、安装好之后下载数据&#xff0c;可以用Blen…...

EXCEL返回未使用数组元素(未使用值)

功能简介&#xff1a; 在我们工作中&#xff0c;需要在EXCEL表列出哪些元素&#xff08;物品或订单&#xff09;已经被使用了&#xff08;或使用了多少次&#xff09;&#xff0c;哪些没有被使用。 当数量过于庞大时人工筛选或许不是好办法&#xff0c;我们可以借助公式&…...

系统调用简单介绍

概述 简单理解就是操作系统给我们提供的函数接口&#xff0c;当我们的程序需要执行一些只有操作系统才能完成的工作的时候&#xff0c;我们就要调用操作系统给我们提供的接口来实现这些功能&#xff0c;这些接口就是系统调用。 那什么样的操作是只有操作系统才能完成呢? 比如…...

Mac可以读取NTFS吗 Mac NTFS软件哪个好 mac ntfs读写工具免费

在跨操作系统环境下使用外部存储设备时&#xff0c;特别是当Windows系统的U盘被连接到Mac电脑时&#xff0c;常常会遇到文件系统兼容性的问题。由于Mac OS原生并不完全支持对NTFS格式磁盘的读写操作&#xff0c;导致用户无法直接在Mac上向NTFS格式的U盘或硬盘写入数据。下面我们…...

AI是否能够做决定

AI是在帮助开发者还是取代他们&#xff1f; 我认为AI功能虽然很强大&#xff0c;但是代替不了人&#xff0c;原因就在于人可以做决定&#xff0c;可以承担责任和后果&#xff0c;但是AI不能够为结果负责...

【Excel操作】Python Pandas判断Excel单元格中数值是否为空

判断Excel单元格中数值是为空&#xff0c;主要有下面两种方法&#xff1a; 1. pandas.isnull 2. pandas.isna判断Excel不为空&#xff0c;也有下面两种方法&#xff1a; 1. pandas.notna 2. pandas.notnull假设有这样一张Excel的表格 我们来识别出为空的单元格 import panda…...

C# Opacity 不透明度

WinForms Opacity以下是一些使用 Opacity 属性的示例&#xff1a;设置窗体的透明度&#xff1a;设置按钮的透明度&#xff1a;动态改变控件的透明度&#xff1a;使用定时器改变透明度&#xff1a;在窗体加载时设置透明度&#xff1a; 请注意另外 WPF Opacity以下是一些使用 Opa…...

推荐三款常用接口测试工具!

接口测试是软件开发中至关重要的一环&#xff0c;通过对应用程序接口进行测试&#xff0c;可以验证其功能、性能和稳定性。随着互联网和移动应用的快速发展&#xff0c;接口测试变得越来越重要。为了提高测试效率和质量&#xff0c;开发人员和测试人员需要使用专业的接口测试工…...

【Qt】Qt多线程编程指南:提升应用性能与用户体验

文章目录 前言1. Qt 多线程概述2. QThread 常用 API3. 使用线程4. 多线的使用场景5. 线程安全问题5.1. 加锁5.2. QReadWriteLocker、QReadLocker、QWriteLocker 6. 条件变量 与 信号量6.1. 条件变量6.2 信号量 总结 前言 在现代软件开发中&#xff0c;多线程编程已成为一个不可…...

PyTorch之nn.Module、nn.Sequential、nn.ModuleList使用详解

文章目录 1. nn.Module1.1 基本使用1.2 常用函数1.2.1 核心函数1.2.2 查看函数1.2.3 设置函数1.2.4 注册函数1.2.5 转换函数1.2.6 加载函数 2. nn.Sequential()2.1 基本定义2.2 Sequential类不同的实现2.3 nn.Sequential()的本质作用 3. nn.ModuleList参考资料 本篇文章主要介绍…...

C++Primer Plus 第十四章代码重用:编程练习,第4题

CPrimer Plus 第十四章代码重用&#xff1a;编程练习,第4题 CPrimer Plus 第十四章代码重用&#xff1a;编程练习,第4题 文章目录 CPrimer Plus 第十四章代码重用&#xff1a;编程练习,第4题前言4.一、定义二、方法 前言 4. Person 类保存人的名和姓。除构造函数外&#xff…...

01 Docker 概述

目录 1.Docker简介 2.传统虚拟机 vs 容器 3.Docker运行速度快的原因 4.Docker基本组成三要素 5.Docker 平台架构 入门版 架构版 1.Docker简介 Docker是基于Go语言实现的云开源项目。 Docker的主要目标是&#xff1a;Build, Ship and Run Any App, Anywhere&#xff0c…...

c++的const

const在C中是一个非常重要的关键字&#xff0c;用于定义不可变的变量、函数参数、成员函数等。它可以提高代码的可读性、安全性&#xff0c;并帮助编译器进行优化。 定义常量 使用const定义不可变的变量&#xff1a; const int MAX_SIZE 100;常量指针 指向常量的指针和常量…...

Git不想跟踪某个文件

如果你不想跟踪某个文件&#xff0c;可以将该文件路径添加到 .gitignore 文件中。.gitignore 文件用于告诉 Git 哪些文件或目录应该被忽略&#xff0c;不进行版本控制。以下是具体步骤&#xff1a; 编辑 .gitignore 文件&#xff1a;在项目的根目录下找到或创建一个 .gitignore…...

DB-GPT 文档切分报错

感谢阅读 配置完知识库&#xff0c;进行切分报错切分完成后&#xff0c;进行问答时后台日志报错 配置完知识库&#xff0c;进行切分报错 报的错如下 document sync error cryptography>3.1 is required for AES algorithm pip install -U cryptography 之后重新运行程序 …...

#如何使用 Qt 5.6 在 Android 上启用 NFC

如何使用 Qt 5.6 在 Android 上启用 NFC NFC 技术在 Android 应用开发中变得越来越重要。在本文中&#xff0c;我将介绍如何使用 Qt 5.6 来实现 Android 上的 NFC 功能。这个教程基于一个创建于 8 年 8 个月前的问题&#xff0c;并在 7 年 3 个月前进行了修改&#xff0c;讨论…...

合并排序的数组

题目链接 合并排序的数组 题目描述 注意点 A的末端有足够的缓冲空间容纳BA和B都是排序的 解答思路 最初想到的是双指针&#xff0c;从小到大找到合并B时应该A相应位置应该插入的元素&#xff0c;因为在插入的过程中B的元素会替换A原有位置的元素&#xff0c;所以需要先将A…...

js 复制文本带样式

一键复制带样式的html文本到邮件 <div><div idcopy-content><div style{{ fontSize: 16px,fontWeight: 500, lineHeight: 24px, color: #222, marginBottom: 16px }}>邀请您参加腾讯会议网络研讨会&#xff08;Webinar)</div></div><Button …...

服务器之BIOS基础知识总结

1.BIOS是什么&#xff1f; BIOS全称Basic Input Output System&#xff0c;即基本输入输出系统&#xff0c;是固化在服务器主板的专用ROM上&#xff0c;加载在服务器硬件系统上最基本的运行程序&#xff0c;它位于服务器硬件和OS之间&#xff0c;在服务器启动过程中首先运行&am…...

FFmpeg 实现从摄像头获取流并通过RTMP推流

使用FFmpeg库实现从USB摄像头获取流并通过RTMP推流&#xff0c;FFmpeg版本为4.4.2-0。RTMP服务器使用的是SRS&#xff0c;拉流端使用VLC。 在Linux上查看摄像头信息可使用 v4l2-ctl 工具&#xff0c;查看命令如下&#xff1a; v4l2-ctl --device/dev/video0 --list-formats-e…...

学生管理系统

一、登录 用户类&#xff1a;属性&#xff1a;用户名、密码、身份证号码、手机号码 1、欢迎页面 System.out.println("欢迎来到学生管理系统"); System.out.println("请选择操作1登录 2注册 3忘记密码"); 代码实现&#xff1a; //欢迎页面public static…...

【linux】网络基础(3)——tcp协议

文章目录 TCP协议概括TCP头部格式TCP连接管理建立连接&#xff08;三次握手&#xff09;数据传输确认应答机制捎带应答 滑动窗口丢包问题 拥塞控制延时应达 终止连接&#xff08;四次挥手&#xff09; TCP协议概括 TCP是一个面向连接的协议&#xff0c;在传输数据之前需要建立连…...

[Day 21] 區塊鏈與人工智能的聯動應用:理論、技術與實踐

區塊鏈的智能合約運行機制 區塊鏈技術自比特幣誕生以來&#xff0c;便以其去中心化、安全性和透明性等特點引起了廣泛的關注和應用。而智能合約作為區塊鏈技術的一大創新&#xff0c;進一步擴展了區塊鏈的應用場景&#xff0c;使其不僅僅局限於數字貨幣&#xff0c;還可以應用…...

使用ps给gif动图抠图

目录 导入gif图片 打开时间轴 选择图片 魔棒抠图-初步抠图 套索抠图-精准抠图 导入gif图片 打开时间轴 因为gif动图实际上多张图片实现的效果&#xff0c;所以如果要给gif抠图&#xff0c;就得挨个给每个时间线的图片抠图 点击窗口->时间轴 选择图片 在时间轴上选择要…...

pmp顺利通关总结

目录 一、背景二、总结三、过程 一、背景 人活着总是想去做一些事情&#xff0c;通过这些事情来证明自己还活着。 而我证明自己还会活着并且活得很好的方式和途径&#xff0c;是通过这些东西去让自己有一个明确的边界节点&#xff1b;借此知识来验证自己的学习能力。 我坚定认…...

未来的钥匙在于过去:学历史的真正意义,震惊!历史竟然是偶然的?从历史中寻找未来的方向!

我们自幼接受的教育是&#xff0c;学历史是为了相信历史是必然的。中国人民必然战胜日寇的侵略&#xff0c;解放思想和改革开放必定会发生&#xff0c;和平和发展必定是世界的主题&#xff0c;中国经济必定是高速增长…… 然而&#xff0c;在真正的历史学家眼中&#xff0c;历史…...

ES6自定义模块

在ES6中&#xff0c;我们可以使用 export 和 import 关键字来定义和使用自定义模块。 定义模块 导出&#xff08;export&#xff09; 命名导出&#xff08;Named Exports&#xff09;&#xff1a; 使用 export 关键字来导出模块中的变量、函数、类等。例如&#xff1a; // ma…...

Windows页面错误(Page Fault)写几种c++会导致,此问题的例子

在C中&#xff0c;直接导致Windows页面错误&#xff08;Page Fault&#xff09;的情景较少直接由编程错误引发&#xff0c;页面错误更多是由操作系统在内存管理和虚拟内存机制中处理的。不过&#xff0c;某些编程错误可能导致访问违规&#xff0c;进而间接引起操作系统报告页面…...

AC7801时钟配置流程

一 默认配置 在启动文件中&#xff0c;已经对时钟进行了初始化&#xff0c;默认按外部8M晶振&#xff0c;配置系统时钟为48MHZ&#xff0c;APB为系统时钟的2分频&#xff0c;为24MHZ。在system_ac780x.c文件中&#xff0c;可以找到下面这个系统初始化函数&#xff0c;里面有Se…...

加密与安全_Java 加密体系 (JCA) 和 常用的开源密码库

文章目录 Java Cryptography Architecture (JCA)开源国密库国密算法对称加密&#xff08;DES/AES⇒SM4&#xff09;非对称加密&#xff08;RSA/ECC⇒SM2&#xff09;散列(摘要/哈希)算法&#xff08;MD5/SHA⇒SM3&#xff09; 在线生成公钥私钥对&#xff0c;RSA公私钥生成参考…...

读书笔记-《Spring技术内幕》(三)MVC与Web环境

前面我们学习了 Spring 最核心的 IoC 与 AOP 模块&#xff08;读书笔记-《Spring技术内幕》&#xff08;一&#xff09;IoC容器的实现、读书笔记-《Spring技术内幕》&#xff08;二&#xff09;AOP的实现&#xff09;&#xff0c;接下来继续学习 MVC&#xff0c;其同样也是经典…...

k8s及常用对象简介

文章目录 一、k8s是什么应用程序早期部署形式容器的引入k8s的作用 二、k8s中的常用对象1、Node获取node信息 2、Namespacenamespace的使用 3、Pod生命周期pod的使用 4、DaemonSetDaemonSet的使用 5、Deployment创建deploy 6、ReplicaSet7、StatefulSet创建StatefulSet 8、更新操…...

HTTPS数字证书验证论述

1 概述 网络请求方式通常分为两种&#xff0c;分别是HTTP请求和HTTPS请求&#xff0c;其中HTTP的传输属于明文传输&#xff0c;在传输的过程中容易被人截取并且偷窥其中的内容&#xff0c;而HTTPS是一种在HTTP的基础上加了SSL/TLS层&#xff08;安全套接层&#xff09;的安全的…...

【高考志愿】地质资源与地质工程

目录 一、专业概述 1.1 专业定义 1.2 主要课程 1.3 专业培养目标 二、就业前景和考研方向 三、工作特点和挑战 四、如何培养核心竞争力 五、 地质资源与地质工程专业排名 六、结语 关于高考志愿选择地质资源与地质工程专业&#xff0c;以下是一些详细的介绍和参考信息…...

全网最佳硕士研究生复试简历模板

硕士研究生复试简历模板 ✨ 简介 提供了一个适用于国内硕士研究生复试的个人简历模板。该模板通过统一的“样式”形成规范的Word格式&#xff0c;是目前研究生复试的最佳简历模板之一。模板使用“华文中宋”字体&#xff0c;如您的电脑中未安装此字体&#xff0c;请提前安装。…...

Rocky Linux 9 系统OpenSSH CVE-2024-6387 漏洞修复

Rocky Linux 9系统 OpenSSH CVE-2024-6387 漏洞修复 1、漏洞修复2、修复思路3、修复方案3.1、方案一3.2、方案二 4、总结5、参考 1、漏洞修复 CVE-2024-6387&#xff1a;regreSSHion&#xff1a;OpenSSH 服务器中的远程代码执行&#xff08;RCE&#xff09;&#xff0c;至少在…...

Sping源码(九)—— Bean的初始化(非懒加载)—mergeBeanDefinitionPostProcessor

序言 前几篇文章详细介绍了Spring中实例化Bean的各种方式&#xff0c;其中包括采用FactoryBean的方式创建对象、使用反射创建对象、自定义BeanFactoryPostProcessor以及构造器方式创建对象。 创建对象 这里再来简单回顾一下对象的创建&#xff0c;不知道大家有没有这样一个疑…...

labview技巧——AMC框架安装

AMC工具包的核心概念是队列&#xff0c;队列是一种先进先出&#xff08;FIFO&#xff0c;First In First Out&#xff09;的数据结构&#xff0c;适用于处理并发和异步任务。在LabVIEW中&#xff0c;队列可以用于在不同VI之间传递数据&#xff0c;确保消息的有序处理&#xff0…...

解锁分布式云多集群统一监控的云上最佳实践

作者&#xff1a;在峰 引言 在当今数字化转型加速的时代&#xff0c;随着混合云、多云多集群环境等技术被众多企业广泛应用&#xff0c;分布式云架构已成为众多企业和组织推动业务创新、实现弹性扩展的首选&#xff0c;分布式云容器平台 ACK One&#xff08;Distributed Clou…...

学会拥抱Python六剑客,提高编程效率

在Python语言中&#xff0c;有六个强大的工具&#xff0c;它们被称为"Python六剑客"。而Python六剑客指的是Python中常用的六种功能强大且灵活的工具&#xff0c;它们分别是“切片&#xff08;Slicing&#xff09;&#xff0c;推导列表&#xff08;List Comprehensio…...

mysql 根据当前时间筛选某个时间范围内的数据

1.根据天数筛选 SELECT * FROM coupons WHERE NOW() BETWEEN start_time AND end_time; 在这个查询中&#xff0c;NOW()函数返回当前的日期和时间。BETWEEN操作符用于检查NOW()返回的当前时间是否在start_time和end_time之间&#xff08;包括这两个时间&#xff09;。 注意&a…...

统计学与人工智能:历史渊源与方法比较

统计学与人工智能&#xff1a;历史渊源与方法比较 在当代技术讨论中&#xff0c;统计学和人工智能&#xff08;AI&#xff09;常常被提及&#xff0c;它们各自在数据分析和预测模型中扮演着重要角色。然而&#xff0c;这两种方法是否对立&#xff0c;以及它们之间的关系如何&a…...

使用 docker buildx 构建跨平台镜像

buildx是Docker官方提供的一个构建工具&#xff0c;它可以帮助用户快速、高效地构建Docker镜像&#xff0c;并支持多种平台的构建。使用buildx&#xff0c;用户可以在单个命令中构建多种架构的镜像&#xff0c;例如x86和arm架构&#xff0c;而无需手工操作多个构建命令。此外bu…...

05.C1W4.Machine Translation and Document Search

目录 OverviewWhat you’ll be able to do!Learning Objectives Transforming word vectorsOverview of TranslationTransforming vectors Align word vectorsSolving for RFrobenius normFrobenius norm squaredGradient K nearest neighborsFinding the translationNearest n…...

奥比中光astra_pro相机使用记录

一、信息获取 1、官网 用于了解产品信息 http://www.orbbec.com.cn/sys/37.html 2、开发者社区 咨询问题下载开发部https://developer.orbbec.com.cn/ 二 、windowvs19 1、相机型号 orbbec_astro_pro 根据对应的型号找到需要的包工具 踩坑1&#xff0c;因为这个相机型号…...

探索区块链:颠覆性技术的崛起

目录 一、引言 二、区块链技术概述 三、区块链应用场景 四、区块链面临的挑战 五、区块链的未来展望 六、结语 一、引言 在数字化浪潮的推动下&#xff0c;区块链技术以其独特的去中心化、透明性和不可篡改性等特性&#xff0c;正在逐步改变我们的生活。从金融领域到供应…...

实现Java Web应用的高性能负载均衡方案

实现Java Web应用的高性能负载均衡方案 大家好&#xff0c;我是微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在高并发的网络环境中&#xff0c;负载均衡是确保Web应用程序高性能和可靠性的关键策略之一。本文将探讨如何…...

2024年激光雷达上车提速,车型标配率增长至6.3%

据盖世汽车研究院2024年1-5月激光雷达供应商排行榜显示,国内激光雷达供应商装机量累计超44.5万颗,速腾聚创以43%市占率位居首位,激光雷达装机量持续加速渗透,车型标配率增长至6.3%。2024年1~5月车载激光雷达累计装机量超44.5万颗,2023年同期为11万颗,同比增长304.5%。“激…...

家人们,咱们汽车界有自己的“显眼包”!

现在想换辆新车太难了,选择太多了,挑的眼花缭乱的。就在我一筹莫展的时候,我在店里遇到了传祺新能源E8,属实是没想到虽然它的价格不到25万,但是却拥有着特别抢眼的优势。它的智能化配置很高,5月份传祺E8首次升级OTA后新增了广汽魔方场景设定功能,可以让我自定义设置2000…...

售价53.86万元新款奔驰E350eL插混版正式上市

6月1日,在 2024 粤港澳车展上,新款梅赛德斯-奔驰 E 350e L 插混版正式上市,售价 53.86 万元。外观方面,新车整体依旧延续燃油版车型的样子,标志性的“花生”大灯,大尺寸格栅以及立标等元素均得以保留。尺寸方面,新车也是保持一直,长宽高分别为 5092/1880/1489mm,轴距为…...

GfK中国联合上海市眼镜行业协会举办高层论坛:探索眼镜市场机遇共筑视觉健

中国与上海市眼镜行业协会联合主办的 “视界之窗:瞰见全球及中国眼镜市场未来”高层论坛5月16日在上海成功举行。本次论坛汇聚了上海市眼病防治中心视光中心、上海健康医学院医学技术学院等三十余家专业机构和协会专家,以及上海三联有限公司、上海依视路光学有限公司、卡尔蔡司…...

什么是访问控制漏洞

什么是AC Bugs&#xff1f; 实验室 Vertical privilege escalation 仅通过隐藏目录/判断参数来权限控制是不安全的&#xff08;爆破url/爬虫/robots.txt/Fuzz/jsfinder&#xff09; Unprotected functionality 访问robots.txt 得到隐藏目录&#xff0c;访问目录 &#xff0c;…...

k8s cephfs(动态pvc)

官方参考文档&#xff1a;GitHub - ceph/ceph-csi at v3.9.0 测试版本 Ceph Version Ceph CSI Version Container Orchestrator Name Version Tested v17.2.7 v3.9.0 Kubernetes v1.25.6 安装Ceph-csi Step 1 Download GitHub - ceph/ceph-csi at v3.9.0 rootsd-k8s…...