news 2026/9/12 11:50:18

本地大模型部署实战:Ollama、transformers与llama.cpp协同指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
本地大模型部署实战:Ollama、transformers与llama.cpp协同指南

1. 项目概述:为什么本地跑大模型这件事,现在比三年前更值得认真对待

Ollama、transformers、llama.cpp——这三个词最近半年在技术社区的交叉出现频率,已经不是“工具选型讨论”,而是演变成一种明确的生产力信号:大模型本地化不再是极客玩具,而是一条可落地、可复用、可嵌入工作流的技术路径。我从去年开始系统性地把日常研发、文档生成、代码辅助、甚至客户方案草稿都迁移到本地运行的模型上,不是为了炫技,而是因为实测下来,一次本地推理的响应延迟稳定在800ms以内,比调用任何公有云API都更可控;模型输出不经过第三方服务器,敏感数据零外泄;更重要的是,你可以随时修改提示词、调整温度值、替换system prompt,而不用等厂商发版或申请白名单。这背后支撑的,正是Ollama的容器化封装、transformers的全栈Python生态、以及llama.cpp对C++底层极致压榨带来的跨平台兼容性。尤其当你面对Jetson AGX Orin这类边缘设备,或者只有16GB内存的旧笔记本时,“量化”就不再是性能优化选项,而是能否启动模型的生死线。4-bit量化不是简单地把权重从float32砍成int4,它涉及对称/非对称量化策略选择、分组量化(group-wise quantization)的粒度控制、以及KV Cache的动态精度保留——这些细节直接决定你在Orin上跑7B模型时是卡在加载阶段,还是能流畅生成300字技术方案。很多人卡在第一步:ollama pull太慢。这不是网络问题,而是镜像源没切对;也有人用transformers加载Qwen2-7B-int4后显存爆掉,其实是因为没关掉flash attention的自动启用;还有人编译llama.cpp时在ARM平台反复失败,根源在于CMake配置里漏掉了-DGGML_CUDA=OFF这个强制开关。这篇笔记不讲原理推导,只记录我踩过、修过、验证过的真实路径:从Windows/Mac/Linux三端安装Ollama开始,到用transformers做LoRA微调,再到用llama.cpp在Jetson上部署4-bit GGUF模型,每一步的命令、参数、报错日志、修复动作,全部按真实操作时间线还原。

2. 核心技术栈拆解:Ollama、transformers、llama.cpp各自解决什么问题

2.1 Ollama:让大模型像Docker一样“开箱即用”的封装层

Ollama本质是一个面向终端用户的模型运行时环境,它的核心价值不是替代transformers或llama.cpp,而是把二者复杂的依赖、编译、配置过程,压缩成一条ollama run llama3:8b命令。它内部做了三件关键事:第一,自动下载并校验模型文件(默认从官方仓库拉取,但支持自定义Modelfile指向本地GGUF或Safetensors);第二,根据宿主硬件自动选择后端——Mac用Metal,Linux用CUDA或CPU,Windows用DirectML,完全透明;第三,提供HTTP API和CLI双接口,让前端应用(比如Ollama Desktop、LM Studio)或脚本(curl调用)能统一接入。我对比过纯transformers加载Llama-3-8B-Instruct的流程:需要手动pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121,再装accelerate、bitsandbytes,最后写十几行代码处理device_map和load_in_4bit参数——而Ollama把这些全打包进一个二进制里。但它也有明显边界:Ollama不支持LoRA适配器热加载,不能动态切换tokenizer,也无法细粒度控制attention实现(比如强制用SDPA而非FlashAttention)。所以当你要做微调或深度定制时,Ollama只是起点,不是终点。另外,国内用户常抱怨ollama pull慢,根本原因不是Ollama本身,而是它默认走GitHub Releases下载GGUF文件,而GitHub在国内解析和连接不稳定。解决方案不是换镜像源(Ollama不支持),而是用ollama create命令自己构建Modelfile,把模型文件提前下好放在本地路径,再通过FROM ./models/llama3.Q4_K_M.gguf引用——这样加载速度从15分钟降到8秒。

2.2 transformers:工业级大模型开发的“瑞士军刀”

Hugging Face的transformers库是当前最成熟的Python大模型SDK,它的定位和Ollama完全不同:Ollama解决“怎么跑起来”,transformers解决“怎么用得深”。从模型加载、tokenize、generate,到训练、微调、量化、导出,transformers提供了全链路API。比如量化,transformers支持四种主流方式:bitsandbytes的4-bit NF4量化(需CUDA)、AutoGPTQ的GPTQ量化(需CUDA)、llm_int8量化(CPU友好)、以及最新的AWQ(需专用kernel)。我实测过Qwen2-7B在RTX 4090上的性能对比:bitsandbytes 4-bit NF4推理速度是FP16的2.1倍,显存占用从14.2GB降到3.8GB;而AWQ在相同硬件上快15%,但需要额外编译awq_cpp内核。transformers的另一个不可替代性在于微调生态——LoraConfig、get_peft_model、Trainer类封装了从数据预处理、梯度检查点、混合精度训练到checkpoint保存的全部逻辑。上周我用transformers+PEFT在单张3090上微调Phi-3-mini-4k-instruct,3小时跑完1000步,loss从1.82降到0.41,生成效果明显优于原模型。但transformers也有硬伤:它重度依赖PyTorch生态,一旦遇到CUDA版本冲突(比如torch 2.3.0要求cudnn 8.9.7,而系统自带8.6.0),整个环境就崩;而且对ARM架构支持弱,Jetson上pip install transformers会因编译失败直接退出。这时候就得切到llama.cpp。

2.3 llama.cpp:用C++重写大模型推理的“硬核备胎”

llama.cpp是整个技术栈里最“反直觉”的存在——它用纯C/C++实现LLM推理,不依赖CUDA、不依赖PyTorch、甚至不依赖glibc(可静态链接musl)。它的价值在于极端环境下的确定性:在Jetson AGX Orin上,你没法装PyTorch(NVIDIA官方不提供ARM64 PyTorch wheel),但llama.cpp的CMakeLists.txt里明确写了-DGGML_CUDA=OFF -DGGML_VULKAN=OFF -DGGML_METAL=OFF,强制走纯CPU路径;在树莓派5上,它能用NEON指令集加速,而transformers连numpy都编译不过。llama.cpp的核心创新是GGUF格式——把模型权重、tokenizer、metadata、甚至LoRA适配器都打包进一个二进制文件,且支持分块加载(mmap)、内存映射(memory mapping)、以及多线程KV Cache管理。我对比过llama.cpp和transformers在相同Q4_K_M GGUF模型上的表现:在i7-11800H上,llama.cpp单线程推理速度比transformers+bitsandbytes快12%,因为少了Python GIL锁和Tensor对象创建开销;但在多线程场景下,transformers靠PyTorch的C++ backend能更好利用多核,此时llama.cpp需手动设置-t 8参数指定线程数。最关键的是量化支持:llama.cpp原生支持Q2_K、Q3_K、Q4_K_M、Q5_K_M、Q6_K、Q8_0六种GGUF量化格式,每种都对应不同精度-速度平衡点。比如Q4_K_M在7B模型上比Q8_0省55%内存,但困惑度(perplexity)只升0.8;而Q2_K虽然内存再降30%,但生成文本开始出现语法错误——这说明量化不是越小越好,必须结合任务类型测试。我在农业大模型项目里用Q4_K_M跑CropBERT(7B参数),问答准确率保持92.3%,而Q3_K就掉到86.1%,这就是实测数据的价值。

3. 量化原理与实操:从理论精度损失到真实场景效果衰减

3.1 量化不是“压缩图片”,而是重构数值空间的数学工程

很多人把量化理解为“把float32转成int4节省空间”,这是严重误解。真正的量化是在保持模型函数映射关系的前提下,用离散数值近似连续权重分布的过程。以Q4_K_M为例,它采用分组量化(group-wise quantization):把每32个权重分成一组,每组独立计算scale和zero-point,再用4-bit整数表示该组内权重相对于组均值的偏移量。公式是:
quantized_weight = round((original_weight - group_zero_point) / group_scale)
其中group_scale和group_zero_point是每组动态计算的浮点数,存储在GGUF文件头里。这意味着Q4_K_M不是简单地把所有权重缩放到[0,15]区间,而是为每个权重块建立局部坐标系——这大幅降低了量化误差,尤其对权重分布不均匀的FFN层特别有效。我用Python写了个小脚本对比Q4_K_M和Q8_0的权重分布:加载Llama-3-8B的layer.12.mlp.gate_proj.weight,画出原始float32、Q8_0 int8、Q4_K_M int4的直方图,发现Q4_K_M在峰值区域(±0.5)的保真度接近Q8_0,但在长尾区域(>2.0)误差放大3倍。这解释了为什么Q4_K_M适合通用对话(依赖中间层激活),而Q2_K在生成长代码时容易出错(依赖高幅值权重)。量化带来的精度损失不是均匀的,而是集中在特定层、特定通道——这也是为什么llama.cpp允许你对不同层设置不同量化等级(比如attention.wv用Q6_K,mlp.down_proj用Q4_K_M),但目前Ollama和transformers都不支持这种细粒度控制。

3.2 三种主流量化路径的实操对比:bitsandbytes vs AWQ vs GGUF

量化方式工具链硬件依赖典型模型显存占用(7B)推理速度(RTX4090)微调支持部署难度
bitsandbytes 4-bit NF4transformers + bitsandbytesCUDA 11.8+Llama-3-8B, Qwen2-7B3.8GB128 tokens/s✅ LoRA中(需配置load_in_4bit)
AWQAutoAWQ + transformersCUDA 12.1+Llama-3-8B, Phi-3-mini4.1GB147 tokens/s❌(需重训)高(需编译awq_cpp)
GGUF Q4_K_Mllama.cpp + llamafileCPU/ARM/MetalAll GGUF models4.3GB92 tokens/s (CPU), 135 tokens/s (CUDA)❌(需重新量化)低(单文件部署)

实操中我踩过两个典型坑:第一,用bitsandbytes量化Qwen2-7B时,如果没加bnb_4bit_quant_type="nf4"参数,它会默认用fp4,导致显存不降反升(因为fp4需要额外存储scale);第二,AWQ量化后的模型无法直接用transformers.load_pretrained,必须用AutoAWQForCausalLM.from_quantized()加载,且tokenizer要单独传入——这点文档里没写清楚,我调试了3小时才找到正确调用方式。GGUF的优势在于部署极简:把llama3.Q4_K_M.gguf文件丢到Jetson的/models/目录,执行./main -m /models/llama3.Q4_K_M.gguf -p "你好" -n 128 -t 8,立刻出结果。但缺点是模型转换成本高——要把Hugging Face的Safetensors转成GGUF,得先用llama.cpp/convert-hf-to-gguf.py脚本,这个脚本对tokenizer.json解析有bug,遇到Qwen2的特殊token会报错,必须手动修改脚本里的tokenizer_config.json读取逻辑。

3.3 边缘设备实战:Jetson AGX Orin上部署llama.cpp的完整链路

Jetson AGX Orin(32GB RAM + 2048-core GPU)是目前最主流的边缘AI平台,但它的CUDA环境和桌面版差异极大。我花了两周时间打通全流程,关键步骤如下:
第一步:环境初始化

# 切换到Ubuntu 20.04(Orin官方支持版本) sudo apt update && sudo apt install -y build-essential cmake python3-pip # 安装ARM64专用PyTorch(官网下载.whl文件,注意版本匹配) pip3 install torch-2.1.0+cu118-cp38-cp38-linux_aarch64.whl # 编译llama.cpp(必须关CUDA,Orin的CUDA驱动不兼容llama.cpp的CUDA backend) cd llama.cpp && make clean && make LLAMA_CUBLAS=0 -j$(nproc)

第二步:模型转换与优化

# 下载Qwen2-7B的Safetensors(约13GB) git lfs install && git clone https://huggingface.co/Qwen/Qwen2-7B-Instruct # 转换为GGUF(重点:指定--no-tokens参数跳过tokenizer转换,避免报错) python3 convert-hf-to-gguf.py Qwen2-7B-Instruct --outtype q4_k_m --no-tokens # 生成的qwen2.Q4_K_M.gguf约4.2GB,用sha256sum校验完整性

第三步:性能调优
Orin的CPU是Cortex-A78,支持SVE指令集,但llama.cpp默认不启用。我在CMakeLists.txt里加了-march=armv8.2-a+simd+fp16+sve编译flag,再用taskset -c 0-5 ./main -m qwen2.Q4_K_M.gguf -p "水稻病害识别" -n 256 -t 6绑定6个CPU核心,实测吞吐量从42 tokens/s提升到68 tokens/s。更关键的是KV Cache优化:默认llama.cpp用-c 2048设置context length,但Orin内存带宽有限,我把-c降到1024,同时加--no-mmap参数禁用内存映射,反而降低延迟抖动——这是因为Orin的LPDDR4x内存随机访问延迟高,mmap会触发大量page fault。

4. 全流程实操指南:从零部署一个可商用的本地大模型服务

4.1 Windows/macOS/Linux三端Ollama部署避坑手册

Ollama官方安装包对Windows支持最差,尤其Win7已彻底放弃(官网明确标注“Windows 10+ required”)。我实测过Win7上强行运行Ollama 0.1.32,会因缺少bcrypt.dll崩溃。正确路径是:Windows用户必须用WSL2(Ubuntu 22.04)。以下是三端统一部署流程:
Windows(WSL2)

# 启用WSL2 wsl --install # 进入Ubuntu wsl # 下载Ollama Linux版(不是Windows版!) curl -fsSL https://ollama.com/install.sh | sh # 验证 ollama --version # 应输出0.1.32 # 拉取模型(重点:用国内镜像加速) OLLAMA_HOST=0.0.0.0:11434 ollama run llama3:8b

macOS(M1/M2/M3)

# 直接下载dmg安装(推荐) # 或用Homebrew(但Homebrew版常滞后) brew install ollama # 加速下载(改host绕过GitHub) echo "140.82.113.3 github.com" | sudo tee -a /etc/hosts ollama run llama3:8b

Linux(Ubuntu 22.04)

# 官方一键脚本 curl -fsSL https://ollama.com/install.sh | sh # 如果遇到权限错误,手动添加用户到ollama组 sudo usermod -a -G ollama $USER newgrp ollama # 启动服务 systemctl enable ollama && systemctl start ollama

常见问题:Error: could not connect to ollama app。这90%是防火墙问题。在WSL2里执行sudo ufw disable,在macOS里检查“系统设置→隐私与安全性→防火墙”是否关闭。另一个高频问题是模型拉取失败,此时不要反复retry,而是用ollama list看已缓存模型,再用ollama rm <model>清理,最后用OLLAMA_NO_CUDA=1 ollama run llama3:8b强制CPU模式启动——很多GPU驱动冲突问题都能绕过。

4.2 transformers微调实战:用LoRA在单卡3090上微调Phi-3-mini

Phi-3-mini-4k-instruct是微软发布的4K上下文小模型,参数仅3.8B,非常适合本地微调。我用transformers+PEFT在单张RTX 3090(24GB)上完成全流程:
数据准备
收集200条农业技术问答对(如“水稻纹枯病症状是什么?”→“叶片出现椭圆形水渍状病斑…”),转成Alpaca格式JSONL:

{ "instruction": "水稻纹枯病症状是什么?", "input": "", "output": "叶片出现椭圆形水渍状病斑,后期病斑融合成云纹状,湿度大时产生白色菌丝。" }

微调脚本核心参数

from transformers import TrainingArguments, Trainer from peft import LoraConfig, get_peft_model lora_config = LoraConfig( r=8, # rank,越大越拟合但越慢 lora_alpha=16, # alpha,控制缩放强度 target_modules=["q_proj", "v_proj"], # 只微调attention的q/v矩阵 lora_dropout=0.1, bias="none" ) training_args = TrainingArguments( output_dir="./phi3-lora", per_device_train_batch_size=4, # 3090最大安全值 gradient_accumulation_steps=8, # 模拟batch_size=32 learning_rate=2e-4, num_train_epochs=3, save_steps=100, logging_steps=10, fp16=True, # 必开,否则OOM optim="adamw_torch_fused", # 加速优化器 report_to="none" ) trainer = Trainer( model=model, args=training_args, train_dataset=dataset, data_collator=data_collator, tokenizer=tokenizer ) trainer.train()

关键经验:per_device_train_batch_size=4是3090的临界值,设5就会OOM;gradient_accumulation_steps=8让有效batch_size达到32,保证梯度稳定性;fp16=True必须开启,否则显存直接爆。训练完成后,用peft.merge_and_unload()合并LoRA权重到base model,生成的merged_model可直接用Ollama加载:ollama create phi3-agri -f Modelfile,其中Modelfile内容为:

FROM ./phi3-lora/merged_model PARAMETER num_ctx 4096 SYSTEM """ 你是一个农业技术专家,只回答作物种植、病虫害防治、土壤管理相关问题。 """

4.3 llama.cpp生产化部署:构建可监控的HTTP API服务

Ollama自带API,但生产环境需要更高可控性。我用llama.cpp的server模式搭建了企业级API:

# 编译带server支持的llama.cpp make server -j$(nproc) # 启动服务(绑定到内网IP,禁用公网访问) ./server -m ./models/llama3.Q4_K_M.gguf -c 2048 -t 8 --port 8080 --host 192.168.1.100

然后用Python写了个轻量级监控脚本:

import requests, time, psutil while True: try: # 检查API健康状态 r = requests.get("http://192.168.1.100:8080/health") if r.status_code != 200: print("API down!") # 触发重启逻辑 os.system("pkill -f 'server -m'") time.sleep(2) os.system("./server -m ./models/llama3.Q4_K_M.gguf -c 2048 -t 8 --port 8080 --host 192.168.1.100 &") # 监控内存使用 mem = psutil.virtual_memory() if mem.percent > 90: print(f"Memory usage {mem.percent}%!") # 清理旧进程 os.system("pkill -f 'llama.cpp'") except Exception as e: print(f"Health check failed: {e}") time.sleep(30)

这个方案比Ollama更可靠:API响应超时可精确到毫秒级(--timeout 120参数),模型加载失败会直接退出而非卡死,且支持标准Prometheus指标暴露(需加--metrics参数)。上周客户现场部署时,Orin设备因散热不足导致CPU降频,llama.cpp自动触发--cpu-mask参数限制使用高温核心,保障了服务可用性——这是Ollama做不到的底层控制力。

5. 常见问题与排查技巧实录:那些文档里不会写的真相

5.1 “Ollama下载太慢了”的10种真实解法

网络搜索里90%的“Ollama国内镜像源”都是无效信息,因为Ollama根本不走镜像源。真实解法只有五种:

  1. Modelfile本地加载法(最稳):
FROM ./models/llama3.Q4_K_M.gguf PARAMETER num_ctx 8192 SYSTEM "You are a helpful AI assistant."

ollama create my-llama3 -f Modelfile,全程不联网。
2.代理中转法(需自建):
在服务器上起一个nginx反向代理:

location /api/models/ { proxy_pass https://registry.ollama.ai/; proxy_set_header Host registry.ollama.ai; }

然后OLLAMA_HOST=http://your-server:8080 ollama run llama3:8b
3.GitHub Release镜像法
手动下载GGUF文件(https://github.com/ollama/ollama/releases/tag/v0.1.32 → assets里找ollama-darwin-arm64),解压后cp ollama /usr/local/bin/,再用ollama serve启动服务。
4.离线包法(企业场景):
ollama export llama3:8b > llama3.tar导出模型包,拷贝到离线机器后ollama import < llama3.tar
5.DNS污染规避法
/etc/hosts里加140.82.113.3 github.com(GitHub IP),比改DNS更直接。

其他所谓“加速插件”“修改config.json”全是误导——Ollama的下载逻辑硬编码在Go二进制里,无法通过配置修改。

5.2 transformers加载失败的三大隐性陷阱

陷阱一:CUDA版本错位
现象:ImportError: libcudnn.so.8: cannot open shared object file
真相:PyTorch wheel绑定了特定cudnn版本,而系统apt install libcudnn8装的是旧版。
解法:conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia,用conda统一管理。

陷阱二:Tokenizer不兼容
现象:KeyError: 'chat_template'
真相:新版本transformers要求tokenizer.json里有chat_template字段,但很多老模型没有。
解法:手动编辑tokenizer.json,加:

"chat_template": "{% for message in messages %}{{ '<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant\n' }}{% endif %}"

陷阱三:FlashAttention冲突
现象:RuntimeError: Expected all tensors to be on the same device
真相:FlashAttention 2.0默认启用,但某些量化模型不支持。
解法:加载模型时加attn_implementation="eager"参数,强制用PyTorch原生attention。

5.3 llama.cpp编译失败的ARM架构专项修复

Jetson Orin编译llama.cpp失败,90%是以下三个原因:

  1. CMake版本过低:Orin Ubuntu 20.04默认cmake 3.16,而llama.cpp要求3.21+。
    解法:wget https://github.com/Kitware/CMake/releases/download/v3.25.2/cmake-3.25.2-linux-aarch64.sh && sudo bash cmake-3.25.2-linux-aarch64.sh --skip-license --prefix=/usr
  2. OpenMP缺失fatal error: omp.h: No such file or directory
    解法:sudo apt install libomp-dev
  3. BLAS库冲突undefined reference to 'sgemm_'
    解法:编译时加-DBLAS_LIBRARIES="/usr/lib/aarch64-linux-gnu/libopenblas.so",指定OpenBLAS路径。

最后分享一个硬核技巧:在Orin上用tegrastats实时监控GPU利用率,如果GR3D_FREQ长期低于50%,说明llama.cpp没用上GPU——此时要检查是否误开了-DGGML_CUDA=ON,或者CUDA驱动版本不匹配(Orin需CUDA 12.2+)。

提示:所有量化模型都存在“精度-速度-内存”三角约束,不存在“又快又准又省”的万能解。Q4_K_M是当前最均衡的选择,但务必用你的业务数据做A/B测试——我曾用Q4_K_M跑金融问答,准确率91.2%,换成Q5_K_M后升到93.7%,而Q3_K掉到84.5%。数据才是唯一裁判。

注意:llama.cpp的-t参数不是线程数越多越好。在Orin上设-t 8-t 16快17%,因为超过8线程会触发内存带宽瓶颈;而在i9-13900K上-t 16-t 8快23%,因为DDR5带宽足够。永远用perf stat -e cycles,instructions,cache-misses ./main ...测真实硬件指标,别信理论值。

我在农业大模型项目里最终锁定的方案是:Ollama做开发调试(快速迭代prompt),transformers做LoRA微调(精准提升领域效果),llama.cpp做生产部署(稳定压测通过)。三者不是替代关系,而是像齿轮一样咬合——Ollama的Modelfile可以引用transformers微调后的模型,llama.cpp的GGUF又能从transformers导出。这种组合拳打法,让我在三个月内把客户现场的作物病害识别响应时间从云端API的3.2秒降到本地0.47秒,准确率从86%提升到94.3%。技术选型没有银弹,只有在真实场景里反复验证过的路径,才是值得抄的作业。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 11:47:04

LQR控制在汽车主动悬架系统中的应用与优化

1. 项目概述&#xff1a;主动与被动悬架控制的本质差异汽车悬架系统作为连接车身与车轮的关键部件&#xff0c;直接影响着车辆的乘坐舒适性和操纵稳定性。传统被动悬架采用固定参数的弹簧-阻尼系统&#xff0c;其性能在设计阶段就已确定&#xff0c;无法适应复杂多变的路况。而…

作者头像 李华
网站建设 2026/9/12 11:46:48

WebSocket调试利器wscat:命令行工具实战指南

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

作者头像 李华
网站建设 2026/9/12 11:46:01

Swift开发IDE怎么选?Xcode与VS Code对比指南

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

作者头像 李华
网站建设 2026/9/12 11:45:32

网络安全零基础入门全解:认知、心法、行业与职业详解

前言 什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 如何成为一名黑客 很多朋友在学习安全方面都会半路转行&#xff0…

作者头像 李华
网站建设 2026/9/12 11:44:25

C++多线程编程:lock_guard的原理与应用

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

作者头像 李华