尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
OpenSSL 1.1.1 编译集成与TLS握手排错实战
简介OpenSSL_1.1.1 面向在 Windows 32 位环境下开发或维护 SSL/TLS 通信程序的 C/C 开发者提供一套可直接取用的运行库、开发头文件、链接库与离线帮助文档用于证书生成、加解密调用及安全网络通信功能集成。压缩包约 16.22MB共约 2000 个文件类型以 HTML 帮助文档和 C 头文件为主辅以 DLL 动态库、LIB 导入库、PDB 调试符号及 openssl 可执行程序分别承担 API 参考查阅、接口声明、运行时加载、编译链接与命令行操作等用途。已有 1052 人学习下载说明其在 Windows 平台 OpenSSL 配置场景中具有一定参考价值。读者可据此了解 bin、include、lib、html 等目录的分工掌握头文件包含、库文件链接与 32 位依赖匹配的基本思路并借助命令行工具完成证书请求、自签名证书和加解密等常见任务为排查编译链接错误、搭建本地安全通信环境提供较完整的资料支撑。1. 一次握手失败的现场还在翻 OpenSSL 1.1.1 的理由前阵子排查一个老服务的握手失败日志里只留了干巴巴一句 handshake failure服务端跑的是几年前编译的 OpenSSL 1.1.1客户端是刚换的新系统。两边抓包一对比才发现问题不在证书也不在网络而在SECLEVEL这个几乎没人注意的默认值上——新系统把它调高了老服务端还在旧档位1024 位的老密钥直接被判死刑。这类问题在 OpenSSL 1.1.1 上特别常见它是第一个把 TLS 1.3 正式塞进主线、同时把内部结构体全部改成不透明的长期支持分支API 表面看只是删了几个函数实际牵动的是初始化、线程、证书校验三套机制。手上这份 OpenSSL 1.1.1 资源包价值就在这里——它给了一个能自己编译、自己验证、自己改openssl.cnf的完整底座。适合两类人一是维护存量 C/C 服务、被系统自带版本卡住的后端二是要做 TLS 行为对照实验、需要精确控制协议版本和套件的安全验证岗。后面按编译、命令行验证、代码集成、排错、进阶五段拆每段都能直接抄。2. 从源码到可用库OpenSSL 1.1.1 的构建链路2.1 为什么不建议直接吃系统包多数发行版自带的 openssl 是打包者二次配置过的产物--prefix被摊到/usr--openssldir指向发行版自己的证书目录编译参数里还被塞了-DOPENSSL_TLS_SECURITY_LEVEL2之类的宏。你在本机跑得好好的命令换台机器就报ee key too small根子往往在这儿。自己从资源包编译一遍最大的收益不是性能是把「版本、编译选项、配置文件位置」这三件事攥在自己手里——出问题时能确定变量。另一个现实原因是多版本共存。系统里有 1.0.2、有 1.1.1、也可能有 3.x动态库 soname 各不相同1.1.1 出的是libssl.so.1.1但头文件路径只有一个默认的/usr/include/openssl。不装到独立前缀编译期和运行期拿到的版本很容易对不上这种错最难查因为程序能编过、能启动只在特定调用上崩。所以第一步永远是选一个干净的--prefix。2.2 三条命令搭起独立前缀解包之后先确认版本别拿错压缩包——1.1.1 系列的小版本号藏在补丁字母里1.1.1w和1.1.1a差了两年多的安全修复。tar -xzf openssl-1.1.1w.tar.gz cd openssl-1.1.1w # 确认版本与构建脚本都在避免下到半截包 head -5 CHANGES ls Configure config VERSION.dat接着配置。Linux 下用./config就够了它会自己嗅探架构并生成Makefile只有交叉编译或要指定特殊目标时才动./Configure。./config \ --prefix/opt/openssl-1.1.1 \ --openssldir/opt/openssl-1.1.1/ssl \ shared zlib \ -fPIC这行配置里每个参数都有指向--prefix是库、头文件、openssl可执行文件的安装根装到/opt下是为了跟系统包彻底隔离。--openssldir单独指出来是因为它存放openssl.cnf和信任证书目录。生产环境常把/opt/openssl-1.1.1/ssl做成只读挂载跟可写的二进制目录分开管理。shared生成.sono-shared只出.a。要单个二进制丢到容器里跑、不想带LD_LIBRARY_PATH就选no-shared要给多个进程共享、或者需要运行时替换补丁版本就选shared。zlib打开压缩支持。注意 1.1.1 默认是no-zlib这点跟 1.0.2 相反从老版本迁过来的构建脚本经常在这里翻车——配置不报错但某个功能突然不可用。-fPIC只在「静态库要被链进自己的.so」时必须普通可执行文件不需要。配置完成后三条命令走完make -j$(nproc) make test make install_swmake test别跳。它会跑一遍自带的回归集涵盖大数运算、各套件加解密、证书链校验。这一步耗时几分钟但它能在你写第一行业务代码之前就把「CPU 不支持某指令集」「系统时间异常」「熵不足」这类环境问题暴露出来。install_sw而不是install是个很实际的选择install会额外装 man 手册页过程中依赖一堆 Perl 模块在精简过的构建镜像里经常中断。install_sw只装软件本体库、头文件、二进制够用。2.3 参数表与产物体检参数作用什么时候必须改--prefix安装根目录永远要改避免污染/usr--openssldir配置与证书目录需要只读挂载或独立备份时shared/no-shared动态库 / 静态库单文件部署选后者zlib传输压缩依赖压缩的场景1.1.1 默认关no-asm关汇编优化交叉编译报汇编错误时用来定位enable-ec_nistp_64_gcc_128P-256 定点加速x86_64 支持__int128的 gcc--cross-compile-prefix交叉工具链前缀交叉编译必填装完立刻体检别等出问题再回头查/opt/openssl-1.1.1/bin/openssl version -a ls /opt/openssl-1.1.1/lib ls /opt/openssl-1.1.1/lib/pkgconfigversion -a会打出编译时间、OPENSSLDIR、engines目录和编译器版本这四行信息以后每次排错都用得上。lib下应该能看到libssl.so.1.1、libcrypto.so.1.1和对应的.apkgconfig下应该有openssl.pc、libssl.pc、libcrypto.pc后面集成时靠它拿编译参数。再验一下 pkg-config 能不能正确解析export PKG_CONFIG_PATH/opt/openssl-1.1.1/lib/pkgconfig pkg-config --modversion openssl pkg-config --cflags --libs openssl输出里如果混进了/usr/include说明PKG_CONFIG_PATH没生效或者系统里还有另一份.pc排在前面这时候别急着往下走先把路径顺序理干净。3. 用命令行把证书链和握手拆开看3.1 verify 与 s_client 各管一段这两个命令经常被混着用其实职责完全不同。openssl verify只做一件事拿你给的信任锚去校验一张证书能不能走到根全程不联网、不握手。它适合离线排查「证书链到底缺哪一环」。openssl s_client是真的去连服务端走完整握手然后把对端发来的证书链、协商出的协议版本、套件、验证结果全部打出来。它适合回答「线上实际发生了什么」。排查顺序我一般反过来先s_client看现象再verify做离线复现最后回到代码里核对校验参数。# 只看结论输出短适合脚本里做巡检 HOSTtarget.internal openssl s_client -connect ${HOST}:443 -servername ${HOST} -brief /dev/null-servername不能省。现在几乎没有单证书单站点的部署了不带 SNI 扩展服务端会返回默认站点的证书你校验的压根不是你以为的那张。/dev/null是防止s_client连上后傻等标准输入。-brief在 1.1.1 里可用输出被压成几行协议版本、套件、验证结果码、对端证书摘要。巡检脚本里解析这一段比解析完整输出稳得多。要看完整证书链就换成-showcertsopenssl s_client -connect ${HOST}:443 -servername ${HOST} -showcerts /dev/null \ | openssl crl2pkcs7 -nocrl -certfile /dev/stdin \ | openssl pkcs7 -print_certs -noout这条管道的作用是把 PEM 块抽出来、转成 PKCS#7 再列出主题和签发者比肉眼在几百行输出里找s:和i:快。3.2 证书链校验的三个输入verify有三个输入维度弄混了就会得出错误结论-CAfile信任锚只能放根证书或你明确信任的中间证书。-untrusted中间证书用来补链条它本身不被信任只是「候选」。位置参数待校验的叶子证书。openssl verify \ -CAfile root.crt \ -untrusted intermediate.crt \ -show_chain \ server.crt-show_chain会把走通的链条一层层打出来成功时输出server.crt: OK加上链深度失败时给的是错误码20是找不到本地签发者缺中间证书21是叶子签名验不过多半是链给错了10是过期18是自签名。这几个码在代码里对应X509_V_ERR_*常量排查时能直接对上。一个常见误用是把中间证书塞进-CAfile。这样verify确实会返回 OK因为中间证书变成了信任锚但真实客户端不会这么干——它只信根。本地测通了、上线全挂就是这么来的。正确姿势永远是-CAfile只放根中间证书走-untrusted。3.3 从握手输出里读协议与套件1.1.1 支持 TLS 1.3但套件选择用了两套参数这是最容易踩的地方# TLS 1.2 及以下用 -cipher openssl s_client -connect ${HOST}:443 -tls1_2 \ -cipher ECDHE-RSA-AES128-GCM-SHA256 -brief /dev/null # TLS 1.3 用 -ciphersuites-cipher 对它无效 openssl s_client -connect ${HOST}:443 -tls1_3 \ -ciphersuites TLS_AES_128_GCM_SHA256 -brief /dev/null原因在协议设计TLS 1.3 的套件只描述对称加密和哈希密钥交换和签名算法被拆到独立的扩展里协商所以旧的-cipher字符串格式压根表达不了。你在 1.1.1 上传-cipher却指定-tls1_3命令不报错但套件过滤静默失效抓包看到的还是默认套件——这种「不报错的失效」最耗时间。验证服务端到底支不支持 1.3最直接的办法是分别用-tls1_2和-tls1_3各连一次看Protocol那一行。如果-tls1_3报no protocols available要么服务端没开要么它跑的根本不是 1.1.1 及以上版本。3.4 本地起一个 s_server 做对照线上环境不可控最好的办法是在本机搭一个已知配置的对端用来做 A/B 对照。# 自签一张测试证书只用于本地 openssl req -x509 -newkey rsa:2048 -nodes -days 30 \ -keyout /tmp/key.pem -out /tmp/cert.pem \ -subj /CNlocalhost # 起服务端限定只跑 TLS 1.2 openssl s_server -accept 4433 -cert /tmp/cert.pem -key /tmp/key.pem \ -tls1_2 -www # 另一个终端连上去 openssl s_client -connect 127.0.0.1:4433 -brief /dev/nulls_server -www会返回一个状态页里面有本次会话的完整参数包括会话 ID、套件、是否复用。改一行服务端参数、连一次、看差异比对着线上服务猜快得多。这个方法在后面调SECLEVEL和协议下限时会反复用。4. 接进自己的程序1.1.1 的 API 边界4.1 初始化模型变了老代码要删三行1.1.1 之前每个进程启动时都得手动调一串初始化函数还要注册线程锁回调否则多线程下会随机崩。1.1.1 把这些全部改成惰性自动初始化老代码里的三行现在是空操作或者宏/* 1.0.2 时代的写法1.1.1 里已无必要 */ SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings();能编过但会带deprecated警告。更麻烦的是CRYPTO_set_locking_callback()这类函数1.1.1 里它变成了空实现——你注册的回调根本不会被调用代码看起来「加了锁」实际上靠的是库内部的原子操作逻辑上没毛病但如果老代码围绕这个回调写了自定义同步逻辑那部分逻辑现在是死代码得清掉。真要显式初始化用新接口OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);第二个参数是OPENSSL_INIT_SETTINGS传 NULL 表示走默认。加载字符串表只影响报错信息的可读性不影响功能排错阶段建议开着。4.2 一个最小 TLS 客户端下面这段能编能跑覆盖了 1.1.1 里最容易写错的几处SNI、主机名校验、错误栈。#include stdio.h #include string.h #include netdb.h #include sys/socket.h #include unistd.h #include openssl/ssl.h #include openssl/err.h #include openssl/x509v3.h /* 把线程/当前错误队列掏空每步失败都调否则报错会串到下一步去 */ static void drain_errors(const char *stage) { unsigned long code; char buf[256]; while ((code ERR_get_error()) ! 0) { ERR_error_string_n(code, buf, sizeof(buf)); fprintf(stderr, [%s] %s\n, stage, buf); } } static int tcp_connect(const char *host, const char *port) { struct addrinfo hints, *res NULL, *p; int fd -1; memset(hints, 0, sizeof(hints)); hints.ai_family AF_UNSPEC; hints.ai_socktype SOCK_STREAM; if (getaddrinfo(host, port, hints, res) ! 0) return -1; for (p res; p ! NULL; p p-ai_next) { fd socket(p-ai_family, p-ai_socktype, p-ai_protocol); if (fd 0) continue; if (connect(fd, p-ai_addr, p-ai_addrlen) 0) break; close(fd); fd -1; } freeaddrinfo(res); return fd; } int main(int argc, char **argv) { const char *host (argc 1) ? argv[1] : 127.0.0.1; const char *port (argc 2) ? argv[2] : 4433; const char *ca (argc 3) ? argv[3] : NULL; SSL_CTX *ctx NULL; SSL *ssl NULL; int fd -1; OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); /* TLS_client_method 是 1.1.1 的统一入口SSLv23_method 已是废弃别名 */ ctx SSL_CTX_new(TLS_client_method()); if (ctx NULL) { drain_errors(SSL_CTX_new); return 1; } /* 协议下限显式钉死别依赖默认值 */ SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); /* 1.1.1 默认是 SSL_VERIFY_NONE不显式打开就等于完全不校验证书 */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); if (ca ! NULL SSL_CTX_load_verify_locations(ctx, ca, NULL) ! 1) { drain_errors(load_verify_locations); goto done; } ssl SSL_new(ctx); if (ssl NULL) { drain_errors(SSL_new); goto done; } /* SNI虚拟主机部署下不带这行会拿到默认站点的证书 */ SSL_set_tlsext_host_name(ssl, host); /* 主机名校验走 X509_VERIFY_PARAM1.1.1 里没有 SSL_set1_host 这个函数 */ { X509_VERIFY_PARAM *param SSL_get0_param(ssl); X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); if (X509_VERIFY_PARAM_set1_host(param, host, 0) ! 1) { drain_errors(set1_host); goto done; } } fd tcp_connect(host, port); if (fd 0) { perror(connect); goto done; } if (SSL_set_fd(ssl, fd) ! 1) { drain_errors(SSL_set_fd); goto done; } if (SSL_connect(ssl) ! 1) { drain_errors(SSL_connect); goto done; } printf(protocol%s\ncipher%s\nverify%ld\n, SSL_get_version(ssl), SSL_get_cipher(ssl), SSL_get_verify_result(ssl)); done: if (ssl ! NULL) SSL_free(ssl); if (fd 0) close(fd); if (ctx ! NULL) SSL_CTX_free(ctx); return 0; }几个关键点在注释里点了这里补充逻辑SSL_get0_param返回的是内部参数的借用指针不能释放跟X509_VERIFY_PARAM_new出来的所有权完全不同。搞混了就是双重释放。X509_VERIFY_PARAM_set1_host的第三个参数传 0 表示主机名按 NUL 结尾字符串算传非 0 则是显式长度。传 0 在主机名含中间 NUL 时有边界风险但正常域名场景够用。SSL_connect返回 1 才是成功返回 0 是「对端优雅关闭」返回负数是错误——负数还要再区分SSL_ERROR_WANT_READ/WRITE非阻塞 socket 需要重试和真正的协议错误。上面这段用的是阻塞 socket所以非 1 一律当错误处理。4.3 链接与运行时库定位编译时把路径全写死避免依赖环境变量PREFIX/opt/openssl-1.1.1 gcc -O2 -Wall -Wextra client.c -o client \ -I$PREFIX/include \ -L$PREFIX/lib \ -Wl,-rpath,$PREFIX/lib \ -lssl -lcrypto-lssl -lcrypto的顺序不能反。libssl依赖libcrypto链接器是单遍扫描反过来会报一堆undefined reference。-Wl,-rpath把运行时搜索路径直接嵌进 ELF比LD_LIBRARY_PATH可靠——后者会被sudo、systemd、容器 entrypoint 悄悄清掉是「本机好好的、部署就起不来」的高频原因。编完立刻验证真的链到了哪个版本ldd ./client | grep -E ssl|crypto objdump -T ./client | grep -i SSL_connectldd看的是运行期依赖objdump -T看的是符号绑定版本。两处都指向/opt/openssl-1.1.1/lib才算干净。如果ldd里冒出/usr/lib/x86_64-linux-gnu/libssl.so.3说明 rpath 没生效或者被更高优先级的路径盖住了这种程序能启动但会在某个特定调用上返回意料外的结果。4.4 错误栈怎么读OpenSSL 的错误不是单个返回值而是一个线程局部的队列。一次失败可能压进去好几条每条包含库编号、函数编号、原因编号。unsigned long code ERR_get_error(); char buf[256]; ERR_error_string_n(code, buf, sizeof(buf)); fprintf(stderr, %s\n, buf);输出形如error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure。三段分别是库、函数、原因。看第三段最有用——alert handshake failure是对端主动发的告警说明问题在对端wrong version number说明你连到了一个非 TLS 端口certificate verify failed才是本地校验问题。一个容易忽略的点ERR_get_error()是弹出操作取一条少一条。调试时想看全部就循环取到返回 0别只取一条就以为只有一条。5. 避坑与排查编译期与握手期的真实记录5.1 编译链接阶段现象undefined reference to SSLv23_client_method代码在 1.0.2 上编得好好的。原因1.1.1 把一堆旧方法名改成了宏或者干脆删了SSLv23_client_method变成TLS_client_method的别名但在某些编译选项下不展开。更常见的是头文件用了新的、链接的库还是系统的 1.0.2符号表里根本没有。解决先ldd确认库版本再全局搜一遍代码里的旧方法名统一换TLS_*_method。如果是第三方库引出来的把它的构建参数也改成新前缀别只改自己的。现象编译通过一运行就Segmentation fault栈在SSL_CTX_new里面。原因头文件和库版本错位。新头文件里SSL_CTX是不透明类型结构体大小按 1.1.1 算老库里的结构体布局完全不同SSL_CTX_new内部按老尺寸写内存越界。解决pkg-config --cflags --libs openssl的输出必须指向同一个--prefix。检查PKG_CONFIG_PATH顺序也检查有没有残留的/usr/include/openssl被优先搜索到。现象make test在某个算法用例上卡住或者失败但编译全过。原因三种可能——CPU 不支持某指令集老 ARM 板子常见、容器里熵池不够导致随机数初始化阻塞、系统时间偏离太大让证书用例失效。解决先用no-asm重新配置一遍排除汇编路径再查/proc/sys/kernel/random/entropy_avail时间问题用date -u对一下容器里挂载宿主时钟通常能解决。5.2 握手阶段现象客户端报ee key too small或dh key too small服务端日志里什么都没有。原因SECLEVEL默认档位被提高了。1.1.1 上游默认是 level 1RSA 至少 1024 位但不少发行版打包时改成 2RSA 至少 2048 位、禁用 SHA1 签名。同一份代码在不同机器上表现不同源头就是编译宏。解决openssl ciphers -v DEFAULTSECLEVEL1对比一下能选出的套件数量确认是不是这个原因。真要降档在openssl.cnf里显式写CipherString DEFAULTSECLEVEL1别改编译宏——配置可查、可回滚编译宏改完就埋进去了。现象-tls1_3 -cipher TLS_AES_128_GCM_SHA256不生效握手用的还是默认套件。原因TLS 1.3 的套件走-ciphersuites-cipher只作用于 1.2 及以下而且不报错。解决分成两条参数写1.2 的放-cipher1.3 的放-ciphersuites。代码里对应SSL_CTX_set_cipher_list和SSL_CTX_set_ciphersuites两个函数别只调前者。现象浏览器访问正常自己的客户端报verify error:num20:unable to get local issuer certificate。原因服务端没下发完整的中间证书链。浏览器有 AIA 自动补链机制会自己去下载缺失的中间证书命令行和自研客户端不会。解决s_client -showcerts数一下服务端发了几张证书正常应该是叶子 中间。服务端侧把中间证书拼进证书文件顺序是叶子在前、中间在后或者客户端用SSL_CTX_load_verify_locations的第二个参数指定一个存放中间证书的目录。现象多线程服务跑一段时间后偶发崩溃栈里有CRYPTO_开头的函数。原因老代码还在调CRYPTO_set_locking_callback以为自己在加锁实际上 1.1.1 里这是空实现。真正的问题往往是别处——比如多个线程共用一个SSL_CTX却没做引用计数或者把SSL对象跨线程传递。解决1.1.1 内部已经线程安全删掉锁回调相关代码。SSL_CTX可以共享SSL对象必须一线程一个。共享SSL是设计错误不是加锁能救的。6. 进阶SECLEVEL 调档、性能自测与上线前对拍真正让 1.1.1 在生产里稳住的是把它当「可配置组件」而不是「黑盒依赖」。最值得先动的是openssl.cnf里的系统默认段1.1.1 起这套配置结构跟 1.0.2 完全不同openssl_conf openssl_init [openssl_init] ssl_conf ssl_sect [ssl_sect] system_default system_default_sect [system_default_sect] MinProtocol TLSv1.2 CipherString DEFAULTSECLEVEL2 Options -SSLv3三层嵌套看着啰嗦但这是 1.1.1 唯一能让所有基于该库的程序都继承配置的写法。openssl_conf是入口ssl_conf指到 SSL 配置节system_default再指到具体参数。写完用openssl ciphers -v验证实际生效的套件列表比读文档靠谱。性能这块别信第三方评测自己跑一遍十分钟的事# 对称加密吞吐 openssl speed -evp aes-256-gcm -seconds 3 # 非对称签名/验签 openssl speed rsa2048 ecdsap256 # 看当前 CPU 走了哪条优化路径 /opt/openssl-1.1.1/bin/openssl version -a | grep -i compiler\|platformaes-256-gcm那行如果吞吐明显低于同机器上系统自带版本基本可以断定汇编优化没启用——回去查--prefix配置时有没有误加no-asm或者 CPU 是否支持 AES-NI。speed命令的输出单位是每秒操作数跨版本对比时注意用同一台机器、同一-seconds参数。上线前我一定会做一次对拍本机s_server配一套已知参数线上服务抓一份真实握手两边用同样的s_client命令连逐行比Protocol、Cipher、Verify return code三行。差异出现在哪一行问题就锁定在哪个环节。这个习惯是从一次SECLEVEL事故之后养成的——那次本地全绿、线上全红折腾了大半天才发现是编译宏不同。从那以后我每次动 OpenSSL 版本或者改openssl.cnf都强制把这三行对拍走一遍确认无误再发。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

YOLOv5单目测距落地指南:标定、地平面法与工程避坑

YOLOv5单目测距落地指南:标定、地平面法与工程避坑

简介:这是一份面向计算机视觉学习者以及自动驾驶、机器人导航方向开发者的 YOLOv5 单目测距 Python 实现包,重点解决仅凭单目摄像头估算目标距离、减少深度传感硬件依赖的问题。压缩包共 132 个文件,约 13.87MB,其中 yaml、yml 用…

📅 2026/11/6 5:28:31
YOLOv5单目测距:USB摄像头像素框转三维坐标实战

YOLOv5单目测距:USB摄像头像素框转三维坐标实战

简介:YOLOv5单目测距(Python)实现方案面向计算机视觉入门到中阶开发者,也适合在自动驾驶、机器人导航、智能监控等方向做场景验证的工程人员,核心解决单摄像头条件下如何由二维图像推断目标距离的问题:先用…

📅 2026/11/6 5:28:31
利用python中matplotlib.pyplot库绘制图

利用python中matplotlib.pyplot库绘制图

plot 绘制折线图import matplotlib.pyplot as pltplt.plot(x,y) # x,y是每个点的坐标,plot()把每个点按顺序画折线scatter 绘制散点图import matplotlib.pyplot as pltplt.scatter(x,y)可以设置color属性,设置颜色也可以导入数据绘制。只需指定好x y…

📅 2026/11/6 5:23:31
MORE NEWS

更多资讯

📰

记忆机制:对话内与跨对话的记忆

很多人对大模型记忆有一个根深蒂固的误解:以为对话多了,模型就"认识"你了,就"记得"你上周说过什么。这个错觉很危险,因为它把工程的归工程的、模型的归模型的,全搅在了一起。今天我把这件事讲清楚…

📰

激光共聚焦显微镜:从原理到应用的全面解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

一文读懂Prometheus+Grafana监控体系(进阶篇)

本文深入探讨PrometheusGrafana监控体系(进阶篇),涵盖背景分析、原理剖析、实战步骤、配置示例、优化建议和避坑指南。最近在处理DevOps与运维相关项目时,PrometheusGrafana监控体系(进阶篇)成为团队讨论最…

📰

关于ELK日志分析平台搭建(进阶篇),你需要知道的一切

本文深入探讨ELK日志分析平台搭建(进阶篇),涵盖背景分析、原理剖析、实战步骤、配置示例、优化建议和避坑指南。很多团队在DevOps与运维场景中都会遇到与ELK日志分析平台搭建(进阶篇)相关的挑战。本文结合生产环境经验…

📰

Pinyon Shift 原生渲染器深度解析:从PM4命令流到EDRAM、Resolve与纹理解码的完整指南

【免费下载链接】pinyon-shift A playable preview of Forza Horizon static recompilation 项目地址: https://gitcode.com/gh_mirrors/pi/pinyon-shift 点击查看 免费下载 Pinyon Shift 把 Xbox 360 版《Forza Horizon》重新编译为 PC 原生程序,其核心…

📰

英语副词详解

一、什么是副词?副词是修饰动词、形容词、其他副词、介词短语、从句或整个句子的词。它的核心功能是提供额外的信息,通常回答以下问题:如何 (How)? 何时 (When)? 何地 (Where)? 到什么程度 (To what extent)? 以及为什么 (Why)?你可以把…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬