首页
关于道锋
友情链接
公告栏
麟图图床
麟云文件
麟云证书
BH5UVN
Search
1
使用ReDroid打造自己的云手机
4,591 阅读
2
Cloudflare SAAS 接入自选教程
2,595 阅读
3
兽装曲腿制作文档
2,144 阅读
4
CloudFront CDN配置教程
2,124 阅读
5
Frpc使用XTCP不通过服务器传输
2,082 阅读
默认
科学
热力学
Furry
小说
星河野望
手工制作
道具制作
音影
图像工具
计算机
渗透
硬件
编程
网络
记录
AI人工智能
CVE
软件工具
装机教程
C/C++
C#
Go
HTML5+JS+CSS
JAVA
Lua
Rust
PHP
Python2/3
Nodejs
编译
C/C++学习日志
Golang学习日志
Rust开发技巧
Rust学习日志
Rust开发教程
Nonebot2机器人框架
python开发教程
python开发技巧
Python学习日志
ai绘画
电子电路
电路设计
PCB打板
制作实战
无线电
摄影
运维
WEB
KVM云计算
docker
Ansible
代码管理
Kubernetes
Linux
MySQL
shell
集群
Zabbix
Prometheus
数据安全
Redis
istio
ELK
Nginx
Apache
Tomcat
Elasticsearch
Logstash
Kibana
测评
服务器
登录
Search
标签搜索
开源
源码
教程
服务器
环境搭建
摄影
rustlang
Rust
VS CODE
v2ray
bbr
加速
网络优化
拥塞控制
CloudFront教程
CF教程
AWS教程
CloudFront接入
Frpc
Frps
道锋潜鳞
累计撰写
447
篇文章
累计收到
127
条评论
首页
栏目
默认
科学
热力学
Furry
小说
星河野望
手工制作
道具制作
音影
图像工具
计算机
渗透
硬件
编程
网络
记录
AI人工智能
CVE
软件工具
装机教程
C/C++
C#
Go
HTML5+JS+CSS
JAVA
Lua
Rust
PHP
Python2/3
Nodejs
编译
C/C++学习日志
Golang学习日志
Rust开发技巧
Rust学习日志
Rust开发教程
Nonebot2机器人框架
python开发教程
python开发技巧
Python学习日志
ai绘画
电子电路
电路设计
PCB打板
制作实战
无线电
摄影
运维
WEB
KVM云计算
docker
Ansible
代码管理
Kubernetes
Linux
MySQL
shell
集群
Zabbix
Prometheus
数据安全
Redis
istio
ELK
Nginx
Apache
Tomcat
Elasticsearch
Logstash
Kibana
测评
服务器
页面
关于道锋
友情链接
公告栏
友人
iMin博客
特资啦!个人资源分享站
三石的记录
咬一口激动的鱼
中二病晚期の物語
奇梦博客
布丁の小窝
道麟笔记
迷失的小K
koto's Site
西西のBlog
锐冰龙小站
Nick的琐碎日常
渣渣120
猎空のBlog“
Suntの小破站
BG5VXJ-无线电
Abyss博客
麟图图床
麟云文件
麟云证书
BH5UVN
搜索到
447
篇与
的结果
2025-07-11
Ollama离线部署
在当前AI浪潮中,越来越多的企业希望在内网环境中部署自己的大语言模型,既要享受AI带来的效率提升,又要确保数据安全和合规性。Ollama作为一个轻量级的大模型运行平台,为离线部署提供了极佳的解决方案。本文将详细介绍Ollama的离线部署实践,从环境准备到模型运行的完整流程。Ollama架构解析与优势Ollama的设计哲学是"简单而强大"。它将复杂的大模型推理过程封装成简洁的命令行工具,同时提供了灵活的API接口。其核心优势在于对GGUF格式模型的原生支持,这种格式经过量化优化,能够在有限的硬件资源上高效运行大模型。Ollama的架构采用了客户端-服务端分离的设计。服务端负责模型的加载、推理和资源管理,客户端提供用户交互界面。这种架构的好处是可以在一台服务器上运行多个模型实例,多个客户端可以同时访问,实现资源的高效利用。在离线环境中,Ollama的另一个重要优势是其模块化的设计。核心运行时、模型文件、配置文件都是独立的组件,可以分别下载和部署,这为离线安装提供了极大的便利。离线部署环境准备离线部署的第一步是准备完整的安装包。与在线安装不同,离线部署需要预先下载所有必要的组件。核心组件下载# 下载Ollama主程序(在有网络的机器上执行) wget https://ollama.com/download/ollama-linux-amd64 # 下载安装脚本 curl -fsSL https://ollama.com/install.sh -o install.sh这里需要特别注意的是,Ollama的安装脚本默认会从网络下载程序文件,但在离线环境中我们需要修改脚本逻辑,让它使用本地已下载的文件。安装脚本改造安装脚本的改造是离线部署的关键技术点。原始脚本中的网络下载逻辑需要被替换为本地文件复制:# 找到脚本中的下载命令(大约在第XX行) # 原始代码: # curl --fail --show-error --location --progress-bar \ # -o $TEMP_DIR/ollama "https://ollama.com/download/ollama-linux-${ARCH}${VER_PARAM}" # 替换为: cp ./ollama-linux-amd64 $TEMP_DIR/ollama这种改造的核心思想是保持安装脚本的其他逻辑不变(如用户创建、权限设置、系统服务配置等),只修改文件获取的方式。这样可以确保离线安装后的系统状态与在线安装完全一致。模型文件获取策略大模型文件是整个部署过程中最大的挑战,不仅因为文件体积庞大,还因为需要选择合适的模型格式和版本。模型源选择国内用户可以优先选择ModelScope作为模型下载源,它提供了丰富的中文优化模型,下载速度也相对稳定:# ModelScope模型下载示例 # 访问 https://modelscope.cn/models # 搜索目标模型,如 Qwen2.5-7B-Instruct # 下载对应的GGUF格式文件对于需要最新国际模型的用户,HuggingFace仍然是首选,但需要考虑网络访问的问题。GGUF格式的技术优势GGUF(GPT-Generated Unified Format)是当前大模型量化的标准格式,相比原始的FP16或FP32模型,它具有以下技术优势:内存效率:通过INT4、INT8等低精度量化,大幅减少内存占用,使得消费级硬件也能运行大模型。加载速度:优化的文件格式结构,支持内存映射和增量加载,显著提升模型启动速度。推理性能:针对现代CPU和GPU的SIMD指令集进行了优化,在保持精度的同时提升推理速度。Modelfile配置深度解析Modelfile是Ollama的核心配置文件,它定义了模型的行为、参数和提示模板。深入理解Modelfile的各个部分对于定制化部署至关重要。核心指令解析FROM ./codeqwen-1_5-7b-chat-q8_0.gguf TEMPLATE """{{ if .System }}<|im_start|>system {{ .System }}<|im_end|> {{ end }}{{ if .Prompt }}<|im_start|>user {{ .Prompt }}<|im_end|> {{ end }}<|im_start|>assistant {{ .Response }}<|im_end|> """ PARAMETER stop "<|im_start|>" PARAMETER stop "<|im_end|>" PARAMETER temperature 0.7 PARAMETER top_p 0.8FROM指令是模型文件的引用,支持本地路径、URL或已存在的模型名称。在离线部署中,使用相对路径引用本地GGUF文件是最常见的方式。TEMPLATE指令定义了对话模板,这是模型理解对话上下文的关键。不同的模型家族有不同的对话格式,如ChatML、Alpaca、Vicuna等。正确配置对话模板直接影响模型的响应质量。PARAMETER指令用于调整模型的生成参数。temperature控制创意性(0-2,越高越有创意),top_p控制词汇选择的多样性(0-1,越高越多样),stop定义停止词用于控制生成的边界。高级配置技巧对于企业级部署,还可以配置更多高级参数:PARAMETER num_ctx 4096 # 上下文长度 PARAMETER num_predict 256 # 最大生成长度 PARAMETER repeat_penalty 1.1 # 重复惩罚 PARAMETER mirostat 2 # Mirostat采样算法 PARAMETER mirostat_tau 5.0 # Mirostat目标困惑度这些参数的调整需要根据具体的应用场景和性能要求来确定。比如,代码生成任务可能需要更高的num_ctx来处理长代码文件,而创意写作可能需要适当提高temperature。模型创建与管理模型创建是将GGUF文件和Modelfile组合成可运行模型的过程。这个过程涉及模型索引建立、配置验证、资源预分配等多个步骤。创建流程详解# 创建工作目录 sudo mkdir -p /opt/llm/models cd /opt/llm/models # 上传模型文件和配置文件 # - codeqwen-1_5-7b-chat-q8_0.gguf # - modelfile-codeqwen.Modelfile # 执行模型创建 ollama create codeqwen:7b -f ./modelfile-codeqwen.Modelfile创建过程中,Ollama会进行以下操作:文件验证:检查GGUF文件的完整性和格式正确性配置解析:解析Modelfile中的各项配置索引建立:为模型建立内部索引,优化后续加载速度依赖检查:验证系统资源是否满足模型运行要求模型版本管理在企业环境中,通常需要管理多个模型版本。Ollama支持语义化版本管理:# 创建不同版本的模型 ollama create codeqwen:7b-v1.0 -f ./modelfile-v1.Modelfile ollama create codeqwen:7b-v1.1 -f ./modelfile-v1.1.Modelfile # 设置默认版本(latest标签) ollama create codeqwen:latest -f ./modelfile-latest.Modelfile这种版本管理策略让模型的升级和回滚变得简单可控,特别适合需要频繁更新模型的场景。运行时优化与性能调优模型的运行性能直接影响用户体验,特别是在资源受限的环境中。Ollama提供了多种优化手段来提升性能。内存管理优化# 设置环境变量优化内存使用 export OLLAMA_NUM_PARALLEL=2 # 并行请求数量 export OLLAMA_MAX_LOADED_MODELS=1 # 最大加载模型数 export OLLAMA_FLASH_ATTENTION=1 # 启用Flash AttentionOLLAMA_NUM_PARALLEL控制同时处理的请求数量。在内存充足的情况下,可以适当增加这个值来提高并发处理能力。但需要注意的是,每增加一个并行请求,内存消耗会相应增加。OLLAMA_MAX_LOADED_MODELS限制同时加载到内存中的模型数量。对于单模型服务,设置为1可以确保所有内存资源都用于当前模型。OLLAMA_FLASH_ATTENTION启用Flash Attention算法,这是一种内存高效的注意力机制实现,可以显著减少内存占用并提升计算速度。GPU加速配置对于配备GPU的服务器,可以启用GPU加速来大幅提升推理速度:# 检查GPU可用性 ollama run --help | grep gpu # 设置GPU内存分配 export OLLAMA_GPU_MEMORY_FRACTION=0.8 # 启用混合精度计算 export OLLAMA_GPU_PRECISION=fp16GPU加速的效果通常非常显著,特别是对于大参数模型。但需要注意的是,不是所有的量化模型都能完全利用GPU加速,需要根据具体的模型格式和硬件配置来调整。服务化部署与高可用在生产环境中,通常需要将Ollama部署为系统服务,确保高可用性和稳定性。系统服务配置# 创建服务配置文件 sudo tee /etc/systemd/system/ollama.service > /dev/null <<EOF [Unit] Description=Ollama Service After=network-online.target [Service] ExecStart=/usr/local/bin/ollama serve User=ollama Group=ollama Restart=always RestartSec=3 Environment="OLLAMA_HOST=0.0.0.0:11434" Environment="OLLAMA_MODELS=/usr/share/ollama/.ollama/models" [Install] WantedBy=default.target EOF # 启用并启动服务 sudo systemctl daemon-reload sudo systemctl enable ollama sudo systemctl start ollama这个服务配置实现了以下功能:自动重启:Restart=always确保服务异常退出后自动重启,RestartSec=3设置重启间隔为3秒,避免频繁重启。网络绑定:OLLAMA_HOST=0.0.0.0:11434让服务监听所有网络接口,方便远程访问。权限隔离:使用专用的ollama用户运行服务,提高安全性。负载均衡与集群部署对于高并发场景,可以部署多个Ollama实例并配置负载均衡:# Nginx负载均衡配置 upstream ollama_backend { server 192.168.1.10:11434 weight=1; server 192.168.1.11:11434 weight=1; server 192.168.1.12:11434 weight=1; } server { listen 80; location /api/ { proxy_pass http://ollama_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_buffering off; } }这种部署方式可以实现水平扩展,通过增加节点来提高整体处理能力。模型迁移与备份策略在企业环境中,模型的迁移和备份是必须考虑的问题。Ollama的模型文件存储在特定目录中,可以通过文件系统操作来实现迁移。模型文件结构/usr/share/ollama/.ollama/ ├── models/ │ ├── manifests/ │ ├── blobs/ │ └── locks/ └── history/manifests目录存储模型的元数据信息,包括模型配置、版本信息等。blobs目录存储实际的模型文件数据,采用了内容寻址的存储方式,相同的数据块只存储一份。locks目录用于并发访问控制,确保模型文件在加载过程中不被修改。迁移操作实践# 源服务器导出模型 sudo tar -czf ollama-models-backup.tar.gz -C /usr/share/ollama .ollama/ # 目标服务器导入模型 sudo systemctl stop ollama sudo rm -rf /usr/share/ollama/.ollama/ sudo tar -xzf ollama-models-backup.tar.gz -C /usr/share/ollama/ sudo chown -R ollama:ollama /usr/share/ollama/.ollama/ sudo systemctl start ollama这种迁移方式可以完整保留所有模型数据和配置,确保迁移后的功能完全一致。API集成与开发接口Ollama提供了REST API接口,便于与其他应用系统集成。API的设计遵循了RESTful规范,使用JSON格式进行数据交换。核心API接口# 模型推理接口 curl -X POST http://localhost:11434/api/generate \ -H "Content-Type: application/json" \ -d '{ "model": "codeqwen:7b", "prompt": "写一个快速排序算法", "stream": false }' # 对话接口 curl -X POST http://localhost:11434/api/chat \ -H "Content-Type: application/json" \ -d '{ "model": "codeqwen:7b", "messages": [ {"role": "user", "content": "解释一下机器学习的基本概念"} ] }'流式响应:通过设置"stream": true,可以实现流式响应,用户可以实时看到生成过程,提升交互体验。上下文管理:对话接口支持多轮对话,通过维护消息历史来保持上下文连贯性。错误处理与监控在生产环境中,需要实现完善的错误处理和监控机制:import requests import time import logging def ollama_chat(prompt, model="codeqwen:7b", max_retries=3): for attempt in range(max_retries): try: response = requests.post( "http://localhost:11434/api/generate", json={ "model": model, "prompt": prompt, "stream": False }, timeout=60 ) response.raise_for_status() return response.json()["response"] except requests.exceptions.Timeout: logging.warning(f"Request timeout, attempt {attempt + 1}") except requests.exceptions.RequestException as e: logging.error(f"Request failed: {e}") if attempt < max_retries - 1: time.sleep(2 ** attempt) # 指数退避 raise Exception("All retry attempts failed")安全加固与访问控制在企业环境中部署大模型服务,安全性是首要考虑因素。需要从网络访问、用户权限、数据保护等多个维度进行安全加固。网络安全配置# 配置防火墙规则 sudo ufw allow from 192.168.1.0/24 to any port 11434 sudo ufw deny 11434 # 配置反向代理认证 # 在Nginx中添加基本认证 auth_basic "Ollama API"; auth_basic_user_file /etc/nginx/.htpasswd;通过限制网络访问范围和添加认证机制,可以防止未授权访问。模型访问权限控制虽然Ollama本身不提供细粒度的权限控制,但可以通过中间件来实现:# API网关示例 from flask import Flask, request, jsonify import requests app = Flask(__name__) # 用户权限配置 USER_PERMISSIONS = { "user1": ["codeqwen:7b"], "user2": ["codeqwen:7b", "qwen:14b"], "admin": ["*"] } @app.route("/api/generate", methods=["POST"]) def proxy_generate(): # 验证用户身份 api_key = request.headers.get("Authorization") user = validate_api_key(api_key) if not user: return jsonify({"error": "Unauthorized"}), 401 # 检查模型权限 data = request.json model = data.get("model") if not check_model_permission(user, model): return jsonify({"error": "Model access denied"}), 403 # 转发请求到Ollama response = requests.post( "http://localhost:11434/api/generate", json=data ) return response.json()性能监控与运维生产环境中的Ollama服务需要持续的监控和运维。关键指标包括响应时间、内存使用、GPU利用率、错误率等。监控指标收集# 创建监控脚本 cat > /opt/ollama/monitor.sh << 'EOF' #!/bin/bash while true; do # 内存使用率 memory_usage=$(ps -p $(pgrep ollama) -o %mem --no-headers) # GPU使用率(如果有GPU) gpu_usage=$(nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits) # 服务状态检查 if curl -s http://localhost:11434/api/version > /dev/null; then service_status="UP" else service_status="DOWN" fi # 记录到日志 echo "$(date): Memory=${memory_usage}%, GPU=${gpu_usage}%, Status=${service_status}" >> /var/log/ollama-monitor.log sleep 60 done EOF chmod +x /opt/ollama/monitor.sh日志管理# 配置日志轮转 cat > /etc/logrotate.d/ollama << 'EOF' /var/log/ollama*.log { daily rotate 30 compress delaycompress missingok notifempty create 644 ollama ollama postrotate systemctl reload ollama endscript } EOF故障排除与常见问题在实际部署过程中,可能会遇到各种问题。建立完善的故障排除流程可以快速定位和解决问题。常见问题诊断模型加载失败:通常是内存不足或GGUF文件损坏导致。可以通过ollama logs查看详细错误信息。响应速度慢:可能是模型参数设置不当或硬件资源不足。可以调整num_ctx、num_predict等参数优化性能。服务无法启动:检查端口占用、用户权限、文件路径等基本配置。调试工具使用# 查看服务日志 sudo journalctl -u ollama -f # 检查模型状态 ollama list # 测试API连通性 curl http://localhost:11434/api/version # 查看资源使用情况 htop nvidia-smi # 如果有GPU总结与最佳实践Ollama的离线部署虽然涉及多个技术环节,但通过系统化的方法和最佳实践,可以构建稳定、高效的企业级大模型服务。关键在于充分理解每个组件的作用和配置方法,结合实际需求进行优化调整。最佳实践建议:环境标准化:建立标准的部署脚本和配置模板,确保多环境部署的一致性。资源规划:根据预期负载合理配置硬件资源,特别是内存和存储空间。安全优先:从设计阶段就考虑安全因素,实现多层次的安全防护。监控完善:建立全面的监控体系,及时发现和处理潜在问题。文档维护:保持部署文档和操作手册的更新,便于团队协作和问题排查。随着大模型技术的不断发展,Ollama这样的轻量级部署工具将在企业AI应用中发挥越来越重要的作用。掌握其离线部署技术,对于构建自主可控的AI服务具有重要意义。
2025年07月11日
10 阅读
0 评论
0 点赞
2025-07-11
DNS压力测试工具的Go实现
DNS压力测试工具的Go实现:高并发网络编程实战最近开发了一个DNS压力测试工具,主要用于测试DNS服务器的性能和稳定性。这个项目使用Go语言实现,充分利用了Go的并发特性来模拟大量DNS查询请求。项目已经开源在GitHub,这篇文章详细分析一下其中的技术实现和设计思路。DNS协议基础和数据包结构在深入代码分析之前,先了解一下DNS协议的基本结构和工作原理,这对理解后续的实现细节至关重要。DNS消息格式详解DNS协议基于UDP传输(标准情况下),每个DNS消息都有固定的结构格式。一个标准的DNS查询包含以下几个部分:DNS Header (12 bytes) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ANCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NSCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+Header字段解析:ID (16位):查询标识符,用于匹配查询和响应QR (1位):查询/响应标志,0表示查询,1表示响应Opcode (4位):操作码,0表示标准查询RD (1位):期望递归查询标志QDCOUNT (16位):问题部分的条目数ANCOUNT (16位):回答部分的条目数DNS查询段(Question Section)Header之后是查询段,包含要查询的域名和查询类型:Question Section +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / QNAME / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QTYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+QNAME编码:域名使用特殊的编码格式,比如www.example.com会被编码为:3www7example3com0每个标签前面是长度字节,整个域名以0字节结尾。QTYPE常见值:A记录 (1):IPv4地址NS记录 (2):权威名称服务器MX记录 (15):邮件交换记录AAAA记录 (28):IPv6地址TXT记录 (16):文本记录QCLASS:通常为1,表示Internet类别。DNS包大小和传输特性UDP限制:传统DNS over UDP的包大小限制为512字节。如果响应超过这个大小,服务器会设置TC(截断)标志,客户端需要使用TCP重新查询。EDNS扩展:现代DNS实现支持EDNS(0)扩展,允许更大的UDP包(通常4096字节),同时提供额外的功能标志。查询特征:DNS查询通常很小(50-100字节)响应大小变化很大(从几十字节到几KB)查询具有突发性特征大部分查询会被缓存,减少上游服务器负载真实网络中的DNS行为模式理解真实DNS流量的特征对于设计压力测试工具很重要:查询分布特征:80%的查询集中在少数热门域名20%的查询是长尾域名或随机查询恶意查询通常具有高随机性特征时间特征:查询具有明显的时间周期性工作时间查询量显著高于夜间突发事件会导致特定域名查询激增地理特征:本地DNS服务器承载大部分查询跨地区查询延迟明显更高CDN和缓存系统影响查询分布miekg/dns库的设计理念在我们的代码中使用的github.com/miekg/dns库是Go语言中最专业的DNS处理库,它的设计有几个重要特点:完整的RFC兼容性:库实现了DNS相关的所有主要RFC标准,包括基础的RFC 1035、EDNS的RFC 2671、安全扩展DNSSEC等。类型安全的API:msg := new(dns.Msg) msg.SetQuestion(dns.Fqdn(domain), dns.TypeA)通过类型安全的API,避免了手动构建DNS包可能出现的格式错误。性能优化:库内部使用了高效的字节操作和内存管理,避免了不必要的内存分配和拷贝。扩展性支持:支持现代DNS特性如EDNS、DNSSEC、DNS over HTTPS等。了解了这些DNS协议的基础知识后,我们再来看代码实现就更容易理解每个部分的设计考虑了。项目背景和应用场景DNS压力测试在网络基础设施维护中是一个重要的环节。无论是评估DNS服务器的承载能力,还是测试网络防护设备的过滤效果,都需要能够生成大量真实的DNS查询流量。传统的压力测试工具往往功能复杂,配置繁琐,而这个工具专注于DNS查询的核心功能,提供了简洁高效的解决方案。这个工具的主要应用场景包括:DNS服务器性能测试、网络设备压力测试、DNS缓存系统验证、网络安全设备测试等。通过模拟真实的DNS查询流量,可以有效评估目标系统在高负载情况下的表现。架构设计思路整个工具的架构设计遵循了"简单而高效"的原则。核心思路是使用Go的goroutine为每个DNS服务器创建独立的查询线程,每个线程负责向特定的DNS服务器发送连续的查询请求。这种设计的优势在于:// 为每个DNS服务器启动一个goroutine for _, serverAddr := range dnsServers { wg.Add(1) go func(addr string) { defer wg.Done() sendDNSQueries(addr, *mainDomain, qType) }(serverAddr) }每个goroutine都是完全独立的,这意味着如果某个DNS服务器出现问题(比如超时或拒绝连接),不会影响其他goroutine的正常工作。同时,通过sync.WaitGroup来协调所有goroutine的生命周期,确保程序能够优雅地启动和关闭。DNS服务器选择策略工具内置了一个精心选择的DNS服务器列表,涵盖了全球主要的公共DNS服务提供商:dnsServers := []string{ "8.8.8.8:53", // Google DNS "8.8.4.4:53", // Google DNS Secondary "1.1.1.1:53", // Cloudflare DNS "1.0.0.1:53", // Cloudflare DNS Secondary "223.6.6.6:53", // 阿里DNS "223.5.5.5:53", // 阿里DNS Secondary "114.114.114.114:53", // 114DNS "114.114.115.115:53", // 114DNS Secondary // ... 更多服务器 }这个列表的设计考虑了几个因素:地理分布覆盖全球主要区域,确保测试的代表性;服务质量这些都是知名的、稳定的DNS服务提供商;负载分散通过向多个服务器发送请求,避免对单一服务器造成过大压力。这种多目标策略的好处是可以同时测试不同地理位置、不同服务商的DNS服务器性能,获得更全面的测试数据。随机子域名生成算法为了模拟真实的DNS查询场景,工具实现了一个智能的随机子域名生成算法。这个算法的核心思想是生成具有真实域名特征的随机字符串:func generateRandomSubdomain(domain string) string { // 生成2-15级长度的子域名 levels := rand.Intn(14) + 2 // 生成2-15之间的随机数 subdomain := "" for i := 0; i < levels; i++ { subdomain += generateRandomString(rand.Intn(10)+1) + "." } return subdomain + domain }这个算法有几个关键的设计决策:层级数量的随机化:真实的域名结构复杂多样,从简单的二级域名到复杂的多级子域名都存在。通过随机生成2-15层的子域名,可以更好地模拟真实网络环境中的查询模式。字符集的选择:const charset = "123456789abcdefghijklmnopqrstuvwxyz"字符集排除了数字0和字母o,这是一个很细致的考虑。在真实的域名中,为了避免混淆,很多域名注册商都会避免使用容易混淆的字符组合。这种设计让生成的域名更接近真实情况。长度的变化:每个域名级别的长度在1-10个字符之间随机变化,这种变化模拟了真实域名的长度分布特征。短的级别可能代表常见的前缀(如www、mail),长的级别可能代表具体的服务名称或随机标识符。网络连接管理网络连接的管理是这个工具的核心技术点。代码使用了UDP协议进行DNS查询,这是DNS协议的标准传输方式:conn, err := net.Dial("udp", serverAddr) if err != nil { fmt.Printf("Error connecting to DNS server %s: %v\n", serverAddr, err) return } defer conn.Close()使用UDP的原因有几个:性能优势:UDP是无连接协议,没有TCP的三次握手开销,适合高频率的短消息传输;DNS标准:绝大多数DNS查询都使用UDP协议,除非响应数据超过512字节才会回退到TCP;资源效率:UDP连接的系统资源消耗更小,可以支持更高的并发量。连接复用策略:每个goroutine建立一个长连接,然后复用这个连接发送所有查询。这种设计避免了频繁建立和销毁连接的开销,同时保持了代码的简洁性。DNS消息构建和序列化工具使用了第三方库github.com/miekg/dns来处理DNS协议的细节:msg := new(dns.Msg) msg.SetQuestion(dns.Fqdn(subdomain), qType) data, err := msg.Pack()这个库的使用体现了Go语言生态的优势。dns.Fqdn()函数自动处理域名的FQDN(Fully Qualified Domain Name)格式转换,确保域名以点号结尾。msg.Pack()将DNS消息结构体序列化为符合RFC标准的二进制格式。查询类型的处理:qType, ok := dns.StringToType[*queryType] if !ok { fmt.Println("Invalid query type. Please use A, MX, NS, etc.") return }通过dns.StringToType映射表,用户可以使用直观的字符串(如"A"、"MX"、"NS")来指定查询类型,工具会自动转换为对应的数值常量。这种设计大大提高了工具的易用性。并发控制和资源管理Go语言的并发模型是这个工具的核心优势。通过goroutine和channel,可以轻松实现高并发的网络操作:var wg sync.WaitGroup for _, serverAddr := range dnsServers { wg.Add(1) go func(addr string) { defer wg.Done() sendDNSQueries(addr, *mainDomain, qType) }(serverAddr) } wg.Wait()WaitGroup的使用:sync.WaitGroup提供了一种简洁的方式来等待所有goroutine完成。在这个应用中,由于每个goroutine都运行无限循环,wg.Wait()实际上会一直阻塞,直到程序被外部信号终止。goroutine的生命周期管理:每个goroutine都有明确的生命周期,从创建到销毁都有对应的资源管理。defer conn.Close()确保无论goroutine如何退出,网络连接都会被正确关闭。闭包和变量捕获:在启动goroutine时使用了闭包的技巧,通过函数参数传递serverAddr,避免了闭包捕获循环变量可能导致的问题。错误处理策略工具采用了"容错但不静默"的错误处理策略:_, err = conn.Write(data) if err != nil { //fmt.Printf("Error sending DNS query to %s: %v\n", serverAddr, err) }可以看到,发送错误的日志输出被注释掉了。这是一个有意的设计决策:在高并发的压力测试中,网络错误是很常见的(比如目标服务器过载、网络拥塞等),如果每个错误都输出日志,会产生海量的日志信息,反而影响工具的性能和可用性。但连接建立失败的错误仍然会被输出,因为这类错误通常表示配置问题或严重的网络问题,需要用户关注。性能优化考虑内存使用优化:每次查询都会创建新的DNS消息对象,这在高并发场景下可能产生大量的短生命周期对象。Go的垃圾回收器可以很好地处理这种模式,但如果需要进一步优化,可以考虑使用对象池来复用消息对象。CPU使用优化:随机字符串生成是CPU密集型操作,特别是在高频率查询的情况下。当前的实现使用了简单的循环,如果需要更高的性能,可以考虑预生成字符串池或使用更高效的随机数生成算法。网络I/O优化:当前每个UDP连接都是阻塞式的,在极高并发的场景下,可能需要考虑使用非阻塞I/O或者连接池来进一步提升性能。扩展性设计虽然当前的工具功能相对简单,但代码结构为扩展提供了良好的基础:配置参数化:通过flag包提供的命令行参数,用户可以自定义目标域名和查询类型。这种设计为添加更多配置选项(如并发数、查询频率等)提供了框架。模块化设计:子域名生成、DNS查询发送、连接管理等功能都被分离到独立的函数中,便于单独测试和修改。数据输出接口:虽然当前版本没有实现详细的统计功能,但代码结构可以很容易地添加性能监控、成功率统计、响应时间测量等功能。实际使用场景和效果这个工具在实际使用中表现出了很好的效果。在一台普通的个人电脑上,可以轻松生成每秒数千次的DNS查询,足以对大多数DNS服务器产生明显的负载压力。测试DNS服务器性能:通过观察不同DNS服务器的响应情况,可以评估其性能差异和稳定性。网络设备压力测试:可以用来测试防火墙、路由器等网络设备在高DNS查询负载下的表现。DNS缓存验证:通过查询大量不存在的域名,可以测试DNS缓存系统的行为和性能。安全和合规考虑需要特别强调的是,这个工具的设计初衷是用于合法的测试和研究目的。在使用时必须遵守相关的法律法规和服务条款:合理使用:避免对公共DNS服务器造成过度负载,建议在自己的测试环境中使用。监控和控制:建议添加查询频率限制和总查询数量控制,避免无节制的压力测试。透明性:在企业环境中使用时,应该确保相关人员知晓测试活动,避免被误认为是恶意攻击。技术栈总结这个项目充分展示了Go语言在网络编程中的优势:并发模型:goroutine和channel让高并发网络编程变得简单直观。标准库:丰富的网络和系统调用支持,减少了对第三方依赖的需求。生态系统:优秀的第三方库(如miekg/dns)提供了专业的协议支持。部署简便:编译后的单一可执行文件,无需复杂的部署环境。总结这个DNS压力测试工具虽然代码量不大,但涵盖了网络编程、并发控制、协议处理、随机算法等多个技术领域。通过精心的设计,用不到200行的代码实现了一个功能完整、性能优秀的专业工具。从开发的角度来看,这个项目是学习Go语言网络编程和并发编程的一个很好的案例。它展示了如何用简洁的代码实现复杂的功能,以及如何在性能和可维护性之间找到平衡。完整的源代码和使用说明可以在GitHub仓库中找到。如果你对网络编程或DNS技术感兴趣,这个项目提供了一个很好的学习和实验平台。欢迎fork和提交issue,一起完善这个工具。
2025年07月11日
4 阅读
0 评论
0 点赞
2025-07-11
双眼动画路径生成:从物理模拟到串口通信的完整解决方案
双眼动画系统的实现:从物理模拟到串口通信的完整解决方案最近在做一个机器人眼睛动画项目,需要实现逼真的眼球运动和眨眼效果。经过一段时间的开发,完成了一个基于多线程的眼睛动画系统,支持实时的眼球运动模拟、自然的眨眼动画,以及通过串口与硬件设备进行通信。项目代码已经开源在 GitHub,这篇文章详细分析一下其中的技术实现。系统架构设计整个系统采用了三线程架构:一个动画更新线程负责核心的眼球运动和眨眼逻辑计算,两个输出线程分别处理左右眼的数据发送。这种设计的好处是将计算逻辑和I/O操作解耦,确保动画计算的稳定性不受串口通信延迟的影响。// 系统核心结构 typedef struct { float eyeOldX, eyeOldY; // 当前位置 float eyeNewX, eyeNewY; // 目标位置 bool inMotion; // 运动状态 uint32_t moveStartTimeMs; // 运动开始时间 uint32_t moveDurationMs; // 运动持续时间 BlinkState blinkState; // 眨眼状态 float eyeOpenness; // 眼睛开合度 } EyeState;使用了一个共享的EyeState结构体来维护眼睛的完整状态,通过std::mutex保护多线程访问,确保数据一致性。眼球运动算法实现眼球运动的核心思路是模拟人类眼球的真实运动模式:大幅度的跳跃式移动(扫视)和小幅度的微调(微眼跳)。算法设计了一个状态机来控制这两种运动模式的切换。路径生成的数学基础在深入具体算法之前,先要理解整个坐标系统的设计。系统使用了一个以MAP_RADIUS为半径的圆形映射区域,其中MAP_RADIUS = 240像素。这个设计的巧妙之处在于:#define SCREEN_WIDTH 240 #define SCREEN_HEIGHT 240 #define MAP_RADIUS 240实际的可视区域被限制在一个更小的圆形范围内,计算公式为:float effective_radius = (MAP_RADIUS * 2 - SCREEN_WIDTH * M_PI_2) * scale_factor;这里的M_PI_2(π/2)是一个关键的修正因子,它考虑了从方形屏幕到圆形映射的几何变换。通过这种方式,我们可以确保生成的所有眼球位置都在有效的显示范围内,避免眼球"跑出屏幕"的情况。扫视运动(Saccadic Movement)的路径生成扫视是眼球的主要运动模式,特点是快速、大幅度的跳跃。路径生成算法采用了极坐标到直角坐标的转换方法,但用了一种更高效的实现:// 扫视运动的有效半径计算 float r = (MAP_RADIUS * 2 - SCREEN_WIDTH * M_PI_2) * 0.75f; // 首先在X轴上随机选择位置 float relativeX = random_float(-r, r); // 根据圆的方程计算Y轴的最大范围 float maxY = sqrtf(r * r - relativeX * relativeX); float relativeY = random_float(-maxY, maxY); // 转换为绝对坐标 state->eyeNewX = MAP_RADIUS + relativeX; state->eyeNewY = MAP_RADIUS + relativeY;这个算法的核心是圆的方程:x² + y² = r²。给定X坐标后,Y坐标的取值范围就确定了:y = ±√(r² - x²)。这种方法比传统的极坐标转换(x = r*cos(θ), y = r*sin(θ))更高效,因为避免了三角函数的计算。扫视运动的scale_factor = 0.75f意味着眼球的扫视范围被限制在理论最大范围的75%内,这样可以留出一些边界缓冲,让运动看起来更自然。运动持续时间设置为83-166毫秒,这个数值是基于人眼扫视的生理特性确定的:人类的快速扫视通常在50-200毫秒之间完成。微眼跳(Microsaccade)的增量路径算法微眼跳采用了完全不同的路径生成策略——增量式生成。与扫视的绝对位置生成不同,微眼跳是基于当前位置的相对偏移:// 微眼跳的范围计算(约为扫视范围的1/10) float r = (MAP_RADIUS * 2 - SCREEN_WIDTH * M_PI_2) * 0.07f; // 生成相对于当前位置的偏移量 float dx = random_float(-r, r); float h = sqrtf(r * r - dx * dx); float dy = random_float(-h, h); // 应用偏移到当前位置 state->eyeNewX = state->eyeOldX + dx; state->eyeNewY = state->eyeOldY + dy;这种设计的优势是微眼跳不会让眼球产生大幅度的"跳跃感",而是在当前注视点附近进行微小的调整。0.07的缩放因子意味着微眼跳的范围约为扫视范围的1/10,持续时间也更短(7-25毫秒),这完全符合人眼微眼跳的生理特征。运动状态机的路径决策逻辑路径生成的决策逻辑通过一个复杂的状态机实现,它需要在扫视和微眼跳之间做出智能选择:if ((t - state->lastSaccadeStopMs) > state->saccadeIntervalMs) { // 执行扫视运动 // ... 扫视路径生成代码 state->moveDurationMs = random_range(83, 166); state->saccadeIntervalMs = 0; // 标记需要重新计算下次扫视间隔 } else { // 执行微眼跳 // ... 微眼跳路径生成代码 state->moveDurationMs = random_range(7, 25); }这里的关键是saccadeIntervalMs的动态计算。每次扫视结束后,系统会根据当前的凝视缩放因子重新计算下次扫视的间隔时间:uint32_t scaledMaxGazeMs = static_cast<uint32_t>(maxGazeMs * gazeScaleFactor); state->saccadeIntervalMs = random_range(state->moveDurationMs, scaledMaxGazeMs);这种设计让眼球的运动模式更加自然:在大部分时间里进行微小的微眼跳调整,偶尔进行大幅度的扫视运动。运动插值的数学模型为了让眼球运动更加平滑,系统使用了一个特殊的缓动函数进行路径插值:float e = (float)dt / (float)scaledDurationMs; // 线性进度 [0, 1] float e2 = e * e; // e的平方 e = e2 * (3.0f - 2.0f * e); // 平滑步函数: 3e² - 2e³这个函数被称为"平滑步函数"(smoothstep),它的数学表达式是f(t) = 3t² - 2t³。这个函数有几个重要特性:f(0) = 0, f(1) = 1:确保插值在正确的边界f'(0) = 0, f'(1) = 0:保证运动开始和结束时速度为零中间段的导数为正:确保单调递增相比线性插值,这种缓动函数让眼球运动具有"加速-匀速-减速"的特征,更符合人眼的运动模式。边界检测和约束处理虽然路径生成算法理论上会保证所有点都在有效范围内,但在实际实现中,还是需要考虑边界情况的处理。特别是在微眼跳的增量计算中,当前位置靠近边界时,简单的偏移可能会导致越界。代码中通过预先计算有效半径的方式来避免这个问题,但在更复杂的应用场景中,可能需要额外的边界检测和坐标钳制逻辑:// 理论上需要的边界检测(当前代码中通过预计算避免了这个问题) float clamp_to_circle(float x, float y, float center_x, float center_y, float radius) { float dx = x - center_x; float dy = y - center_y; float distance = sqrtf(dx*dx + dy*dy); if (distance > radius) { float scale = radius / distance; return {center_x + dx*scale, center_y + dy*scale}; } return {x, y}; }参数化控制对路径生成的影响用户可调节的参数对路径生成有直接影响:凝视缩放因子(gazeScaleFactor):影响扫视的触发频率,值越大,扫视间隔越长移动速度因子(moveSpeedFactor):通过除法运算延长运动持续时间,从而减慢运动速度// 速度控制的实现 uint32_t scaledDurationMs = static_cast<uint32_t>(state->moveDurationMs / moveSpeedFactor);这种参数化设计让同一套路径生成算法可以适应不同的应用需求,从慢速的冥想状态到快速的警觉状态都能很好地模拟。眨眼动画系统眨眼动画采用了状态机模式,包含三个状态:未眨眼、闭合中、打开中。这种设计可以精确控制眨眼的每个阶段,实现更自然的效果。typedef enum { NOT_BLINKING = 0, BLINK_CLOSING = 1, BLINK_OPENING = 2 } BlinkState;眨眼的触发机制采用了随机间隔,基础间隔为2-6秒,这个数值参考了人类的平均眨眼频率。眨眼动作的持续时间分为两个阶段:闭合阶段50-100毫秒,打开阶段是闭合阶段的2倍,这样可以模拟真实眨眼的不对称特性。参数化控制系统为了让系统更加灵活,设计了一套完整的参数化控制系统。用户可以通过命令行参数调整各种行为:--gazescale: 控制凝视时间,值越大眼睛移动频率越低--movespeed: 控制眼球移动速度,值越小移动越慢--blinkfreq: 控制眨眼频率,值越小眨眼越少--blinkspeed: 控制眨眼速度,值越小眨眼动作越慢这些参数通过乘法因子的方式应用到相应的计算中,比如移动速度的控制:uint32_t scaledDurationMs = static_cast<uint32_t>(state->moveDurationMs / moveSpeedFactor);串口通信协议系统使用JSON格式进行数据传输,这样既保证了数据的结构化,又具有很好的可读性和扩展性。数据包格式如下:{ "req": "c", "d": { "x": 0.25, "y": -0.33, "l": 0.95 } }其中req字段表示请求类型,d字段包含实际的眼睛数据。坐标系统使用了归一化的浮点数,范围从-1.0到1.0,中心点为(0,0)。这种设计的好处是与具体的硬件分辨率无关,接收端可以根据自己的需要进行缩放。串口配置采用了115200波特率,8位数据位,无校验位,1个停止位。为了提高通信的可靠性,在串口初始化时禁用了各种流控制和特殊字符处理:tty.c_cflag &= ~CRTSCTS; // 禁用硬件流控制 tty.c_iflag &= ~(IXON | IXOFF | IXANY); // 禁用软件流控制 tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); // 禁用规范模式时间管理和同步系统使用了clock_gettime(CLOCK_MONOTONIC)来获取高精度的时间戳,这比gettimeofday()更适合做时间间隔计算,因为它不受系统时间调整的影响。帧率控制采用了固定时间步长的方式,设定为40fps(25ms每帧)。这个频率对于眼球动画来说已经足够流畅,同时也不会给系统带来过大的负担:#define FPS 40 #define FRAME_DURATION_MS (1000 / FPS) uint32_t frameDuration = get_time_ms() - frameStart; if (frameDuration < FRAME_DURATION_MS) { delay_ms(FRAME_DURATION_MS - frameDuration); }错误处理和容错机制在串口通信方面,实现了比较完善的错误处理机制。当写入失败时,系统会尝试重新建立连接,这对于长时间运行的设备来说非常重要:if (bytes_written < 0) { close(fd); fd = setup_serial_port(port_name, BAUD_RATE); if (fd < 0) { std::cerr << eye_name << "重新连接串口失败,线程退出" << std::endl; break; } }同时,系统还实现了优雅的退出机制,通过信号处理函数捕获Ctrl+C和SIGTERM信号,确保所有线程能够正常退出并释放资源。性能优化考虑在多线程设计中,为了减少锁竞争,动画更新线程和数据发送线程的工作频率是一致的,都是40fps。数据发送线程每次都会完整复制一份眼睛状态,这样可以最小化临界区的大小。另外,所有的浮点数计算都使用了单精度float,这在保证精度的同时也提供了更好的性能。对于眼球动画这样的应用场景,单精度的精度已经完全足够。扩展性设计系统的设计考虑了很好的扩展性。比如左右眼交换功能的实现,通过一个简单的布尔值就可以改变数据的发送目标,这对于一些特殊的硬件配置很有用。数据格式的设计也很灵活,JSON格式可以很容易地添加新的字段,比如瞳孔大小、眼睛颜色等。坐标系统的归一化设计也使得系统可以适应不同分辨率的显示设备。总结这个眼睛动画系统在技术上实现了几个关键点:基于生理学原理的运动模型、稳定的多线程架构、灵活的参数化控制、可靠的串口通信。整个系统的代码结构清晰,模块化程度高,既可以作为独立的眼睛动画服务使用,也可以很容易地集成到其他机器人项目中。从开发的角度来看,这个项目涉及了实时系统设计、数值计算、串口通信、多线程编程等多个技术领域,是一个很好的综合性项目。如果你对机器人动画或者实时系统开发感兴趣,可以从这个项目中学到不少东西。完整的源代码和详细的使用说明都可以在 GitHub仓库 中找到,欢迎大家fork和提issue讨论。
2025年07月11日
5 阅读
0 评论
0 点赞
2025-07-11
APRS:业余无线电的数字化革命
APRS:业余无线电的数字化革命什么是APRS?APRS(Automatic Packet Reporting System,自动数据包报告系统)是一种实时的数字通信协议,由Bob Bruninga (WB4APR) 在1980年代末开发。它允许业余无线电爱好者通过无线电波传输位置、天气、消息和其他数据信息,创建了一个分布式的实时信息网络。APRS的核心特性实时位置跟踪APRS最为人知的功能是GPS位置跟踪。用户可以:自动发送自己的位置信息在地图上查看其他用户的位置跟踪移动中的车辆、船只或行人消息传递支持点对点的短消息传输,即使在没有互联网连接的情况下也能保持通信。天气数据许多APRS站点配备了天气传感器,可以实时报告:温度和湿度风速和风向降雨量气压应急通信在自然灾害或紧急情况下,APRS成为重要的通信工具,可以:协调救援工作传递关键信息提供备用通信渠道APRS的工作原理数据包结构APRS使用AX.25协议传输数据包,每个数据包包含:呼号(Call Sign)位置坐标时间戳符号和注释路径信息网络拓扑APRS网络采用分层结构:移动站:发送位置和数据的移动设备固定站:提供覆盖区域的固定中继站IGate:连接RF网络和互联网的网关Digipeater:数字中继器,扩展覆盖范围技术规格频率使用北美:144.39 MHz欧洲:144.80 MHz亚洲:144.64 MHz澳洲:145.175 MHz数据传输调制方式:1200 baud AFSK(音频移频键控)协议:AX.25发送间隔:根据移动速度自动调整(通常1-30分钟)所需设备基本配置无线电收发器VHF/UHF业余无线电台支持数据传输模式TNC(Terminal Node Controller)硬件TNC或软件TNC负责数字信号的编解码GPS接收器提供精确的位置信息现代设备通常内置GPS天线系统VHF/UHF天线根据使用场景选择合适类型现代解决方案随着技术发展,出现了集成度更高的设备:手持APRS电台:集成GPS和TNC功能移动APRS单元:专为车载使用设计智能手机应用:通过音频接口连接电台软件生态桌面软件APRSISCE/32:功能强大的Windows APRS客户端Xastir:跨平台的开源APRS软件APRSIS32:流行的Windows APRS应用移动应用APRSdroid:Android平台的APRS客户端PocketPacket:iOS平台的APRS应用在线服务APRS.fi:全球APRS活动的网页查看器aprs.org:官方APRS网站和资源实际应用案例户外活动徒步旅行队伍的位置跟踪自行车比赛的实时监控航海活动的安全保障应急响应地震、洪水等自然灾害的救援协调山区搜救行动的通信支持公共活动的安全保障科学研究野生动物追踪气象数据收集环境监测APRS的优势技术优势自动化:无需人工干预即可传输数据实时性:信息传输延迟低可靠性:多路径传输提高成功率开放性:协议公开,支持自主开发社区优势全球网络:覆盖世界各地免费使用:无需付费服务技术支持:活跃的开发者社区持续发展:不断有新功能和改进挑战与限制技术限制带宽限制:数据传输速率较低覆盖范围:受地形和中继站分布影响频谱拥堵:热点区域可能出现信道拥塞使用门槛执照要求:需要业余无线电操作证书技术知识:需要一定的无线电技术基础设备成本:初始投资相对较高未来发展技术演进数字化升级:向更高效的数字协议迁移互联网融合:与现代通信技术更好集成物联网应用:扩展到更多IoT场景应用拓展智慧城市:参与城市信息化建设应急管理:成为应急通信体系的重要组成教育推广:在STEM教育中发挥作用如何开始使用APRS准备工作获取执照:考取业余无线电操作证书选择设备:根据需求和预算选择合适的设备学习协议:了解APRS的基本原理和操作方法加入社区:参与本地的业余无线电活动首次设置配置设备参数(呼号、位置、符号等)设置合适的发送间隔测试信号覆盖和数据传输在线查看自己的信号是否被正确接收
2025年07月11日
4 阅读
0 评论
0 点赞
2024-12-15
在Ubuntu 24.10下将ONNX模型转换RKNN
文章介绍了 RKNPU 和 RKNN-Toolkit2 的基础知识,详细说明了如何在 Ubuntu 系统上安装工具链,并结合案例展示了如何将模型从 ONNX 转换为 RKNN 格式并部署在 Luckfox Pico 开发板上。
2024年12月15日
640 阅读
0 评论
0 点赞
2024-10-29
Raspi Zero2W USB+TF卡扩展板项目
对Raspi Zero2W进行多功能扩展,可使用emmc或tf卡二选一启动,也附带了usb扩展坞和ups功能,通过弹簧顶针和z2w上的测试点链接
2024年10月29日
130 阅读
0 评论
0 点赞
2024-08-25
新版ubuntu使用pip时发生的错误
新版ubuntu使用pip时发生错误:error: externally-managed-environment × This environment is externally managed ╰─> To install Python packages system-wide, try apt install python3-xyz, where xyz is the package you are trying to install. If you wish to install a non-Debian-packaged Python package, create a virtual environment using python3 -m venv path/to/venv. Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make sure you have python3-full installed. If you wish to install a non-Debian packaged Python application, it may be easiest to use pipx install xyz, which will manage a virtual environment for you. Make sure you have pipx installed. See /usr/share/doc/python3.11/README.venv for more information. note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages. hint: See PEP 668 for the detailed specification.收到一个错误提示: error: externally-managed-environment ,即“外部管理环境”错误,但这不是一个 bug,新的发行版中,正在使用 Python 包来实现此增强功能,这个更新是为了避免操作系统包管理器 (如pacman、yum、apt) 和 pip 等特定于 Python 的包管理工具之间的冲突,这些冲突包括 Python 级 API 不兼容和文件所有权冲突。可以看一下python官方的说明:PEP 668 – Python base environments Python 增强提案 (PEP) 解决方案:1:如果你习惯于原来的用法可以强制删除此警告:sudo mv /usr/lib/python3.x/EXTERNALLY-MANAGED /usr/lib/python3.x/EXTERNALLY-MANAGED.bk注意python版本号写你自己的别直接抄,不知道到底是多少可以进/user/lib看看:find /usr/lib/ -type d -name "*python*"2:老实点使用pipx安装pipx:sudo apt install pipx以后就使用Pipx去安装包文件了:pipx install package_name添加环境变量:pipx ensurepath删除使用pipx安装的软件包:pipx uninstall package_name3:使用venv如果你是专业开发人员,在运行或构建py文件时遇到“ModuleNotFoundError: No module named 'xxx'”错误,推荐使用Python虚拟环境,借助虚拟环境,使用不同版本的包依赖项和Python,避免包之间的任何冲突。安装 venv:sudo apt install python3-venv #或者 sudo apt install python3.10-venv生成Python虚拟环境:mkdir -p $HOME/.env && python3 -m venv $HOME/.env/project_name将看到一个.env在主目录中,并且你将在 .env 中拥有项目目录,每个虚拟环境项目目录中都会有自己的 Python 和 Pip 副本。安装模块:$HOME/.env/project_name/bin/python -m pip install --upgrade pip $HOME/.env/project_name/bin/python -m pip install package_name用新的虚拟环境执行py文件:source $HOME/.env/project_name/bin/activate $HOME/.env/project_name/bin/python ./xxxx.py
2024年08月25日
99 阅读
0 评论
0 点赞
2024-04-04
Cloudflare SAAS 接入自选教程
使用Cloudflare做DNS解析的域名,开启Proxy小云朵后可以获得CDN服务,以提高线路不好或是被墙的ip的访问性。当然启用Proxy后连接的好坏也取决于用户到Cloudflare的连接质量,Cloudflare提供了一些固定的泛播ip,用户如果连接至延迟更高的ip反而会获得“减速”效果。因此本文提供一种方式来定期优选Cloudflare ip并指向自己的域名。
2024年04月04日
2,595 阅读
2 评论
5 点赞
2024-02-15
Linux下使用tcpdump监听DNS查询
Linux下使用tcpdump监听DNS查询 并解决docker connection reset by peer问题
2024年02月15日
235 阅读
0 评论
0 点赞
2024-01-13
使用ReDroid打造自己的云手机
前言市面上已经存在很多云手机厂商如红手指、多多云、雷电云、河马云手机等,价格从几十到上百元每月一台。价格还好说,但设备运行稳定性、可靠性、数据安全性全部依赖第三方厂商,注定不能进行敏感性操作或部署对安全可靠高要求的企业级服务。本文介绍一种开源的 AIC (Android In Container) 解决方案 ReDroid,使用本教程可以在一台普通型服务器运行多个安卓设备环境,并可在客户机电脑连接使用该云手机。Redroid介绍redroid(Remote an Droid)是一个 GPU 加速的 AIC(Android In Cloud)解决方案。Docker您可以在 Linux 主机( 、podman等)中启动多个实例k8s。redroid支持arm64和amd64架构。 redroid适用于云游戏、虚拟化电话、自动化测试等。目前支持:安卓 14 ( redroid/redroid:14.0.0-latest)仅适用于 Android 14 64 位 ( redroid/redroid:14.0.0_64only-latest)安卓 13 ( redroid/redroid:13.0.0-latest)仅适用于 Android 13 64 位 ( redroid/redroid:13.0.0_64only-latest)安卓 12 ( redroid/redroid:12.0.0-latest)仅适用于 Android 12 64 位 ( redroid/redroid:12.0.0_64only-latest)安卓 11 ( redroid/redroid:11.0.0-latest)安卓 10 ( redroid/redroid:10.0.0-latest)安卓 9 ( redroid/redroid:9.0.0-latest)安卓 8.1 ( redroid/redroid:8.1.0-latest)入门redroid 应该能够在任何 Linux 上运行(启用一些内核功能)。这里以使用阿里云的X86服务器进行演示,具体如下:配置:vCPUs2内存2G储存40G系统ubuntu-22.04架构x86-64带宽3M安装Docker## 安装 docker https://docs.docker.com/engine/install/#server # 根据 Docker 官方文档安装Docker curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh #或者从仓库下载 sudo apt update sudo apt-get install -y docker.io systemctl start docker systemctl enable docker 安装内核扩展模块更具不同的系统,有不一样的安装方法,具体如下 # 拉取内核模块源码 git clone https://github.com/remote-android/redroid-modules cd ./redroid-modules # Ubuntu 16.04 / 18.04 / 20.04 sudo apt-get install -y git kmod make gcc linux-headers-`uname -r` sudo make # build kernel modules sudo make install # build and install *unsigned* kernel modules # Ubuntu 20.04+ (kernel 5.0+) sudo modprobe ashmem_linux sudo modprobe binder_linux devices=binder,hwbinder,vndbinder # AmazonLinux2 git checkout origin/amazonlinux2 sudo yum install git kmod make "kernel-devel-uname-r == `uname -r`" sudo make # build kernel modules sudo make install # build and install *unsigned* kernel modules # Alibaba Cloud Linux 2 git checkout origin/alibabalinux2 sudo yum install git kmod make "kernel-devel-uname-r == `uname -r`" sudo make # build kernel modules sudo make install # build and install *unsigned* kernel modules # Alibaba Cloud Linux 3 git checkout origin/alibabalinux3 sudo yum install git kmod make "kernel-devel-uname-r == `uname -r`" sudo make # build kernel modules sudo make install # build and install *unsigned* kernel modules # openEuler 20.03 / kernel 4.19 git checkout origin/openeuler2003 sudo yum install gcc kernel-devel sudo KDIR=/usr/src/kernels/<VER> make install # 检查模块状态 lsmod | grep -e ashmem_linux -e binder_linux # example output: # binder_linux 147456 79 # ashmem_linux 16384 23 # 也可以这样验证 grep binder /proc/filesystems # output should like: nodev binder grep ashmem /proc/misc # output should like: 56 ashmem我这边因为是ubuntu 22.04,便使用 modprobe 安装如果不想换系统,可以尝试升级内核到5.0以上,默认就自带相关模块了启动容器创建Docker-compose文件docker-compose.ymlversion: "3" services: redroid: image: redroid/redroid:11.0.0-latest stdin_open: true tty: true privileged: true ports: - "20055:5555" volumes: # 資料存放在目前目錄下 - ./redroid-11-data:/data command: # 設定libndk相關 - ro.product.cpu.abilist0=x86_64,arm64-v8a,x86,armeabi-v7a,armeabi - ro.product.cpu.abilist64=x86_64,arm64-v8a - ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi - ro.dalvik.vm.isa.arm=x86 - ro.dalvik.vm.isa.arm64=x86_64 - ro.enable.native.bridge.exec=1 - ro.dalvik.vm.native.bridge=libndk_translation.so - ro.ndk_translation.version=0.2.2 - ro.secure=0 cap_add: - CAP_SYS_MODULE 启动容器#确保安装了docker-compose apt install docker-compose # 进入储存docker-compose.yml的目录 cd /data/redroid-1 docker-compose up -d如果使用 22.04可能出现如下异常解决方案pip install 'urllib3<2'链接根据 Scrcpy 官方文档下载安卓投屏软件源码包到客户机,解压使用adb connect ip:5555 # adb devices 可查看连接设备列表 scrcpy --serial ip:5555高级一些额外参数样例docker run -itd --rm --privileged \ --pull always \ -v ~/data:/data \ --cap-add CAP_SYS_MODULE \ -p 5555:5555 \ redroid/redroid:11.0.0-latest \ androidboot.redroid_width=1080 \ androidboot.redroid_height=1920 \ androidboot.redroid_dpi=480 \参数描述默认androidboot.redroid_width显示宽度720androidboot.redroid_height显示高度1280androidboot.redroid_fps显示 FPS30(启用 GPU) 15(未启用 GPU)androidboot.redroid_dpi显示 DPI320androidboot.use_memfd使用 memfd 替换已弃用的 ashmem计划默认启用假androidboot.use_redroid_overlayfs使用overlayfs共享data分区/data-base:共享data分区/data-diff:私有数据0androidboot.redroid_net_ndnsDNS 服务器数量,如果未指定 DNS 服务器,将使用“8.8.8.8”0androidboot.redroid_net_dns<1..N>域名解析 androidboot.redroid_net_proxy_type代理类型;从以下选项中选择:“静态”、“pac”、“无”、“未分配” androidboot.redroid_net_proxy_host androidboot.redroid_net_proxy_port 3128androidboot.redroid_net_proxy_exclude_list逗号分隔列表 androidboot.redroid_net_proxy_pac androidboot.redroid_gpu_mode从以下选项中选择:auto、host、guest;guest:使用软件渲染;host:使用 GPU 加速渲染;auto:自动检测自动androidboot.redroid_gpu_node 自动检测ro.xxxDEBUG 目的,允许覆盖 ro.xxx 属性;例如设置ro.secure=0,则默认提供root adb shell
2024年01月13日
4,591 阅读
1 评论
3 点赞
2023-11-24
第一章 宇宙的琴弦
大会结束的很快,大伙都挺乐意这样。没多久就各回各的岗位上忙碌起来了,天苑族常年作为联盟的主心已经不是一件令他们觉得奇怪的事情,每个龙都觉得这是理所当然的。结束大会后,潜鳞没有在外交上的多耗费太多精力,急匆匆的就奔向了联盟科学院。将大部分事情嘱托给了助手去处理。毫无疑问,他既是联盟最高领袖,又是科学院的一位院士。"老默,怎么样了"。潜鳞看着机甲肘部的通信显示屏上的数据,问到潜鳞在显示屏上点击了几下,从下巴处的护甲上面升起来一块面罩。边说着,边走向了联盟科学院大楼内的一处巨大的气密装置。铿----随着巨大的机械臂落下,气闸门落下,因为减压的作用,舱内泛起白雾。潜鳞找准了舱壁上的一个固定扣具,将机甲背部链接固定到舱壁上。"即将进入环世界背向发射程序。。。"一道机械的合成音响起。地面抖动了一下,开始迅速向下加速冲去。"有发现了,你过来看看吧",对话的那一头回复道。在一段时间的黑暗后,轿厢从环世界背面冲出,在这里,十几道级长无比的纳米长缆,链接到了几千千米外的一处巨大的空间站上。毫无疑问,这是个链接着联盟科学院空间科学研究中心的太空电梯。"进入加速阶段,请保持与轿厢的稳定连接",机械音再次响起。轿厢内链接器进行了一次旋转,将倒立的潜鳞转正,随后,轿厢底部两台霍尔推进发动机瞬间点火。将轿厢以一个恐怖的速度推向远处的研究中心空间站。"你们先整理,我马上到",潜鳞按下位于颈部的通信按钮,说道。"进入空间站亚轨道,准备减速。",几分钟后,随着机械音再次响起,底部两台发动机关机,顶部两台小功率的霍尔发动机开始全功率启动。没一会时间,在计算机的控制下,稳稳的停在了研究中心停靠点上。舱门缓缓打开,残余的空气在这时候被吸入黑暗的真空。泄压产生了一片水雾。默柏,联盟科学院理论物理与空间科学研究所一级研究员,外籍(非龙族),主要领导研究高维度空间。"前段时间,我们背向上辅的这个空间科学中心上,两套互为备份的宇宙微波背景辐射观测设备,同时观测到了千分之一的背景温度波动。背景2.725K的温度,在设备测量精度范围内,出现了0.001K左右的波动。",默柏拿着全息投影向潜鳞说着。"有没有可能是上辅的恒星活动波动产生的射线引起的¿",潜鳞问到"不可能,首先我们的研究中心建在背向环世界的方向,上辅产生的射线暴或者电磁干扰,需要透过厚重的环世界本体,才会到达我们这。更何况,我们环日探测器返回的同时间数据显示,上辅并没有突发的恒星活动。根据我们的推测,有接近6西格玛的标准值水平可以认为是。。。。",默柏卖了个关子。"能量极大的超重弦,以可观测尺度划过宇宙!",潜鳞和默柏异口同声的说到。"这意味着我们在m理论上迈出了及其重要的一步。我们从观测上证明了超重弦的存在",默柏说道:"我把数据发你,你看看"一份折线图被投射到潜鳞肘部的终端上,一条始终在2.725K附近以十万分之一到万分之一波动的折线,在某段时间,赫然变成一个个尖峰,在不同间隔上波动了三次,最终恢复成原先的样子。"三条弦¿""是的,宇宙暴涨时代的杰作。ATB 10的负43次方秒时,暴涨的巨大能量,使卡丘空间中的三个维度,延长到了宇宙学尺度,形成了我们现在的宇宙。而在ATB 10的负43次方秒到 ATB 10的负3次方秒这段时间内,暴涨泡沫的巨大能量,就使得某些重弦,获得了极大的能量,从普朗克长度延伸至宇宙学长度。""三条弦同时划过,这倒是出乎了我意料。原本还以为能观测到一次就是一个大进步了。"神龙联盟的科技树有点严重歪斜的感觉,得益于环世界原文明遗留下来的大量技术资料,联盟的工程学等级奇高,与之相对应的则是平平无奇的一直没有进展的物理学研究。联盟的工程学能力高到已经凭借技术资料,进入曲率引擎研制的时代,但,受限于基础物理学的薄弱,这些遗留技术资料,联盟只能仿制,始终无法突破。联盟的环世界实际上是一个良好的环日加速器载体,几十年之前,在默柏的提议下,联盟启动了环日加速器建设工程。现在的环世界中心,就埋藏着一台巨大的粒子对撞加速器,产生的对撞能量,足以制造较小的可观察的弦圈。但是,他太小了,几个恒星月下来,只能制造出及其微量的简并态物质载体,用于承载较为大的弦。弦的能量主要由振动幅度,弦的强度决定,环日对撞机的极限能量,还是无法产生足够长,足够大的弦圈来观测或实验。联盟版图很大,信息通讯是个问题,加上这种能量态下,默柏和潜麟能做的研究也基本都做了个遍,膜理论的宏大蓝图上依然还缺了些什么。所以,渐渐的,环日加速器开始转向制造用于联盟内星系间通信的引力波发射器核心----发射弦。“普朗克能量尺度下的宏观巨弦,有意思”,潜麟思索了很久。“按照我们的计算,暴涨不止产生了这三根弦。可能还存在数根同样高能的长弦,不过,或许没有这三根这么强。但是,我们。。。。”,默柏抖了下狼耳朵,越说越小声“还需要哪些仪器,我去找尚书省那几个家伙说,给你批经费。无论如何,搞定膜-超弦理论”,潜麟走到太空电梯舱门前,看着玻璃气密窗外的璀璨星河说到。“请进入轿厢,并做好固定·····”,机械音响彻在两人耳边。“老默,你说,还有比这更美的宇宙吗?”“更美的宇宙。。。。。。更美的。。。”,默柏看着远去的潜麟低语。“如果膜理论这块拼图补全了,那,展示给我们的,将是一个达到十一维的宏大世界”,默柏抬头,眼里闪着光。宇宙振动的琴弦,即将演奏一个传奇乐章。
2023年11月24日
211 阅读
3 评论
8 点赞
2023-08-11
D-Link Go-RT-AC750命令注入漏洞复现
D-Link Go-RT-AC750命令注入漏洞复现
2023年08月11日
344 阅读
0 评论
0 点赞
1
2
...
38