深入解析管道(pipe)在进程通信中的核心机制与C++实战应用
1. 从水管到数据流理解管道通信的本质想象一下你家里的水管。水从水厂流出来经过管道最终从你家的水龙头里流出。在这个过程中水管本身不生产水它只负责运输。管道pipe在计算机世界里扮演着几乎一模一样的角色它是一条连接两个进程的“数据水管”让数据可以从一个进程的“水龙头”输出端流向另一个进程的“进水口”输入端。为什么进程之间需要这样一根“水管”呢这得从进程的“自闭症”说起。每个进程在操作系统里都拥有自己独立的“小王国”也就是内存空间。你的微信进程不能直接去翻看浏览器进程正在浏览的网页内容反之亦然。这种隔离是操作系统为了保证安全和稳定而设计的重要机制但也带来了一个问题它们之间怎么“说悄悄话”呢比如你写了一个程序负责收集数据另一个程序负责分析数据你肯定希望它们能高效地协作。这时候就需要一种进程间通信IPC的机制而管道就是其中最基础、最经典的一种。我刚开始接触这个概念时总觉得很抽象。直到有一次我在Linux终端里敲下ls -l | grep .cpp这行命令才恍然大悟。ls -l命令负责列出当前目录下所有文件的详细信息它本应把这些信息直接“吐”到屏幕上。但那个竖线符号|就像一根魔法管道把ls的输出直接导入了grep命令的输入里。grep则像一位筛选员只把包含.cpp的行挑出来展示。这个过程里ls和grep就是两个独立的进程它们通过管道瞬间完成了数据的交接没有创建任何临时文件高效又优雅。这就是管道最直观的威力。那么这根“水管”在系统内部到底是怎么搭建的呢它并不是一个我们能在硬盘上找到的普通文件虽然有一种管道像文件。本质上管道是内核维护的一块内存缓冲区。你可以把它想象成内核空间里的一个“中转站”。当进程A想给进程B发送数据时它需要把数据从自己的“地盘”用户空间搬运到这个“中转站”内核缓冲区。然后进程B再从这个“中转站”把数据搬回自己的“地盘”。内核负责管理这个中转站的秩序比如排队、防止数据混乱等。所以对进程来说操作管道就像读写一个特殊的文件用read和write这些熟悉的文件操作函数就行了底层复杂的搬运工作都由内核默默完成了。2. 匿名管道父子进程间的“悄悄话”通道匿名管道顾名思义它没有名字。这种管道就像一个临时搭建的秘密通道通常只在有“血缘关系”的进程之间使用比如父子进程或者兄弟进程。因为它没有全局可见的标识只有继承了它的文件描述符的进程才知道它的存在。2.1 核心特征与使用场景匿名管道有几个非常鲜明的特点理解了它们你就知道该在什么时候用它了。首先它只能用于具有亲缘关系的进程。这个“亲缘关系”主要是指通过fork()系统调用创建出来的进程家族。父进程创建了管道然后fork()出子进程子进程天然地复制了父进程的文件描述符表于是父子俩就拥有了指向同一个管道缓冲区的“钥匙”文件描述符。这就好像父亲在家里修了一条密道只有他的儿子们知道入口在哪里。其次管道是单向的字节流。这一点至关重要也是新手最容易栽跟头的地方。一个管道一旦创建就固定了数据流向一端只能写另一端只能读。如果你想实现双向对话那就需要创建两个管道一个用于A到B另一个用于B到A。字节流意味着数据像水流一样连续没有像消息队列那样的“包裹”边界。如果进程A先写入“Hello”再写入“World”读进程B可能一次读到“HelloWorld”也可能分两次收到“He”和“lloWorld”。数据的解析完全由读写双方自己约定协议管道不负责帮你分割。再者管道自带同步与阻塞机制。这是它非常智能的一点。当管道里空空如也时试图从读端读取数据的进程会被操作系统挂起阻塞直到有数据写入。反过来如果管道被数据塞满了缓冲区有大小限制试图写入的进程也会被阻塞直到有数据被读走腾出空间。这种机制完美地协调了生产者和消费者的速度防止了数据丢失或程序空转。最后匿名管道是临时的。当所有持有其文件描述符的进程都终止后这个管道也就烟消云散了不会在系统里留下任何痕迹。这非常适合一次性的、任务式的进程协作。2.2 手把手实战用C创建父子进程管道理论说再多不如动手写一行代码。下面我们用一个完整的C例子来看看匿名管道是如何在父子进程间搭建数据桥梁的。这个例子模拟一个经典场景子进程负责产生数据比如模拟传感器读数父进程负责接收并处理数据。#include iostream #include unistd.h #include string.h #include sys/wait.h int main() { int pipefd[2]; // pipefd[0] 用于读pipefd[1] 用于写 char buffer[1024]; ssize_t bytes_read; // 1. 创建管道 if (pipe(pipefd) -1) { std::cerr 创建管道失败 std::endl; return 1; } // 2. 创建子进程 pid_t pid fork(); if (pid -1) { std::cerr 创建子进程失败 std::endl; return 1; } if (pid 0) { // 子进程代码块我们让子进程作为写入方 std::cout [子进程] 启动准备向管道写入数据... std::endl; close(pipefd[0]); // 子进程关闭不用的读端 std::string messages[] {数据包#1, 状态更新#2, 最终报告#3}; for (const auto msg : messages) { std::cout [子进程] 写入: msg std::endl; write(pipefd[1], msg.c_str(), msg.length() 1); // 写入字符串包含结束符\0 sleep(1); // 模拟耗时操作 } std::cout [子进程] 数据发送完毕关闭管道写端并退出。 std::endl; close(pipefd[1]); // 写入完成关闭写端 _exit(0); // 子进程退出 } else { // 父进程代码块作为读取方 std::cout [父进程] 启动等待从管道读取数据... std::endl; close(pipefd[1]); // 父进程关闭不用的写端 // 循环读取直到管道写端被关闭read返回0 while ((bytes_read read(pipefd[0], buffer, sizeof(buffer) - 1)) 0) { buffer[bytes_read] \0; // 确保字符串正确终止 std::cout [父进程] 收到: buffer std::endl; } if (bytes_read 0) { std::cout [父进程] 管道写端已关闭数据读取完毕。 std::endl; } else { std::cerr [父进程] 读取管道时发生错误 std::endl; } close(pipefd[0]); // 关闭读端 wait(nullptr); // 等待子进程结束回收资源 std::cout [父进程] 程序结束。 std::endl; } return 0; }我们来拆解一下这个程序的关键步骤和背后的“坑”pipe(pipefd)这是创建管道的核心系统调用。它创建了一个缓冲区并返回两个文件描述符。pipefd[0]是读端的“门票”pipefd[1]是写端的“门票”。记住这个对应关系很多错误都源于搞混了0和1。fork()创建子进程。神奇的事情发生了子进程完整地复制了父进程的内存和文件描述符表。现在父子进程都持有这两张“门票”都能对同一个管道进行读写。关闭无用端这是建立单向通信的关键一步。在子进程中我们明确close(pipefd[0])因为子进程只写不读。在父进程中我们close(pipefd[1])因为父进程只读不写。如果不关闭不仅逻辑混乱更严重的是会影响管道对“写端关闭”的判断。如果父进程不关闭写端即使子进程退出并关闭了它的写端管道中仍然存在一个写端描述符父进程持有的父进程的read调用就会一直阻塞等待形成死锁。读写操作子进程用write向pipefd[1]写入数据父进程用read从pipefd[0]读取数据。注意我写入时包含了字符串结束符\0这样读出来才能正确打印。这就是前面提到的“字节流”边界需要自己处理。读端感知结束父进程的while循环条件(bytes_read read(...)) 0是关键。当子进程发送完所有数据并close(pipefd[1])后管道中所有的数据被父进程读完后下一次read调用会返回0这标志着“文件结束”EOF循环退出。如果所有写端都关闭了读端还在读就会收到这个结束信号。SIGPIPE信号这是一个重要的陷阱。如果读端被关闭了比如父进程意外崩溃而子进程还在试图向管道写入数据内核会向子进程发送一个SIGPIPE信号默认行为是终止进程。在实际项目中我们可能需要捕获并处理这个信号避免程序无声无息地崩溃。编译并运行这个程序你会看到清晰的父子对话过程。通过这个简单的例子匿名管道的创建、单向通信、阻塞读取和生命周期管理就都串联起来了。3. 命名管道FIFO让陌生进程也能“交个朋友”匿名管道好用但它的“血缘”限制让它的应用场景比较有限。很多时候我们需要两个完全独立启动、互不知情的进程也能通信。比如一个后台的数据采集服务和一个前端的图形显示程序。这时候命名管道Named Pipe也叫FIFO就闪亮登场了。3.1 它到底是个啥和匿名管道的区别你可以把命名管道想象成一个有名字的“特殊文件”。它在文件系统中有一个路径比如/tmp/my_fifo。任何进程只要知道这个路径并且有足够的权限都可以像打开普通文件一样打开它进行读写。这就打破了亲缘关系的壁垒。它的底层机制和匿名管道类似内核同样维护着一块缓冲区。但关键区别在于这个“文件”节点成为了一个全局可见的访问点。创建它的进程服务器可以在文件系统中留下这个“接头地点”然后其他进程客户端就可以找过来“对暗号”了。数据流动的方式依然是先进先出FIFO所以它才被叫做FIFO文件。命名管道有几个典型特征第一它允许无亲缘关系进程间通信这是它最大的价值。第二它在文件系统中持久存在直到被显式删除unlink。第三它的open操作可能阻塞。如果一个进程以只读方式打开一个FIFO它会一直等待直到有另一个进程以写方式打开同一个FIFO通信链路才算真正建立反之亦然。这种阻塞特性常用于进程间的同步。3.2 C实战构建一个简单的客户端-服务器模型让我们用C写一个经典的“客户端-服务器”聊天demo。服务器创建一个命名管道并等待读取客户端打开这个管道并写入消息。为了更贴近实战我们会加入一些错误处理和用户交互。服务器端 (server.cpp)负责创建管道并读取消息#include iostream #include fcntl.h #include sys/stat.h #include unistd.h #include cstring #include cstdlib int main() { const char* fifo_path /tmp/my_chat_fifo; char buffer[256]; // 1. 创建命名管道FIFO文件 // 如果文件已存在mkfifo会失败所以我们先尝试忽略这个错误EEXIST if (mkfifo(fifo_path, 0666) -1) { if (errno ! EEXIST) { // 如果不是“文件已存在”的错误则报错退出 std::cerr 无法创建命名管道: strerror(errno) std::endl; return 1; } else { std::cout [服务器] 命名管道已存在直接使用。 std::endl; } } else { std::cout [服务器] 命名管道创建成功: fifo_path std::endl; } // 2. 以只读方式打开管道这里会阻塞直到有客户端以写方式打开 std::cout [服务器] 等待客户端连接... std::endl; int fd open(fifo_path, O_RDONLY); if (fd -1) { std::cerr [服务器] 打开管道失败: strerror(errno) std::endl; return 1; } std::cout [服务器] 客户端已连接开始接收消息。 std::endl; // 3. 循环读取客户端发来的消息 ssize_t bytes_read; while ((bytes_read read(fd, buffer, sizeof(buffer) - 1)) 0) { buffer[bytes_read] \0; // 确保字符串终止 std::cout [客户端说]: buffer std::endl; // 简单逻辑如果收到 quit则结束会话 if (strcmp(buffer, quit) 0) { std::cout [服务器] 收到退出指令。 std::endl; break; } } if (bytes_read -1) { std::cerr [服务器] 读取错误: strerror(errno) std::endl; } else { std::cout [服务器] 客户端关闭连接服务结束。 std::endl; } // 4. 清理工作 close(fd); // 可选删除管道文件。在实际长驻服务中可能不删除。 // unlink(fifo_path); return 0; }客户端 (client.cpp)负责打开管道并发送消息#include iostream #include fcntl.h #include unistd.h #include cstring #include string int main() { const char* fifo_path /tmp/my_chat_fifo; std::string user_input; // 1. 以只写方式打开管道。如果服务器端还没启动这里会阻塞。 std::cout [客户端] 正在尝试连接服务器... std::endl; int fd open(fifo_path, O_WRONLY); if (fd -1) { std::cerr [客户端] 无法打开管道请确保服务器已启动: strerror(errno) std::endl; return 1; } std::cout [客户端] 连接成功请输入消息 (输入 quit 退出): std::endl; // 2. 循环从标准输入读取并发送到管道 while (std::getline(std::cin, user_input)) { if (write(fd, user_input.c_str(), user_input.length() 1) -1) { // 写入字符串及结束符 std::cerr [客户端] 写入失败: strerror(errno) std::endl; break; } if (user_input quit) { std::cout [客户端] 退出指令已发送。 std::endl; break; } } // 3. 清理 close(fd); std::cout [客户端] 连接关闭。 std::endl; return 0; }编译与运行打开两个终端窗口。 在第一个终端服务器g -o server server.cpp ./server你会看到服务器启动并打印“等待客户端连接...”此时程序在open调用处阻塞。在第二个终端客户端g -o client client.cpp ./client客户端启动并成功连接后两个终端都会解除阻塞。此时在客户端终端输入任意消息回车后消息会立刻显示在服务器终端。在客户端输入quit可以优雅地结束会话。这个例子揭示了命名管道的典型工作模式它像一个“接力棒”或“信箱”。服务器创建信箱并等待取信读阻塞客户端找到信箱并投信写阻塞直到有读者。一旦连接建立数据就可以单向流动了。要实现双向聊天就需要建立两个FIFO文件。4. 性能优化与实战中的“避坑指南”管道用起来简单但在高并发、大数据量或复杂架构的实际项目中如果不注意细节很容易掉进坑里。这里分享一些我踩过坑后总结的经验和优化思路。4.1 缓冲区大小与原子性数据安全的基石管道的缓冲区大小是有限的在Linux系统中你可以通过fcntl函数或读取/proc/sys/fs/pipe-max-size来查看和设置。默认值通常为64KB65536字节。这个大小直接影响性能。小缓冲区问题如果生产数据的速度远快于消费速度写操作会频繁阻塞降低整体吞吐量。在需要高速数据传输的场景如实时日志汇聚可以考虑适当增大缓冲区或者采用多管道并行流。原子写入的黄金法则这是一个至关重要的特性。当一次写入的数据量小于等于PIPE_BUFPOSIX规定至少512字节Linux上通常是4096字节时系统保证这次写入是原子的。这意味着即使有多个进程同时向同一个管道写每个小于PIPE_BUF的消息都不会被其他进程的消息穿插打乱。对于需要传递独立消息包的场景务必确保每个消息包的大小控制在PIPE_BUF以内。如果消息很大就需要在应用层自己设计协议比如在消息头部加上长度字段让读端知道如何拼装。4.2 阻塞与非阻塞I/O避免死锁的钥匙默认情况下管道的读写操作都是阻塞的。这在很多情况下是好事它简化了编程模型。但在复杂的、多路复用的程序中阻塞可能导致整个线程或进程“卡住”。死锁场景想象一个经典的双向通信模型进程A和进程B各用一个管道通信。A从管道1读向管道2写B从管道2读向管道1写。如果两个进程都先执行读操作它们就会互相等待对方先写入数据从而形成死锁。解决方案非阻塞模式与多路复用设置非阻塞标志使用fcntl(fd, F_SETFL, O_NONBLOCK)可以将管道文件描述符设置为非阻塞模式。在此模式下读空管道或写满管道会立即返回-1并设置errno为EAGAIN或EWOULDBLOCK而不是阻塞。这给了程序轮询检查的机会。使用select/poll/epoll这是处理多个I/O通道包括管道、套接字等的更高效方法。它们可以同时监控多个文件描述符的状态当某个管道可读或可写时再通知程序去操作从而避免盲目阻塞。这对于需要同时处理多个客户端管道连接的服务器程序来说是必备技能。// 一个简单的使用fcntl设置非阻塞模式的例子 int set_nonblocking(int fd) { int flags fcntl(fd, F_GETFL, 0); if (flags -1) return -1; return fcntl(fd, F_SETFL, flags | O_NONBLOCK); } // 在管道描述符上调用 set_nonblocking(pipefd[0]);4.3 信号处理SIGPIPE让你的程序更健壮前面提到当向一个读端已经关闭的管道写入数据时内核会向写入进程发送SIGPIPE信号默认行为是终止进程。在命令行工具里这也许没问题。但在一个长期运行的后台服务里因为一个客户端意外断开就导致整个服务崩溃是不可接受的。忽略信号最简单的处理方式是忽略它。#include signal.h signal(SIGPIPE, SIG_IGN);设置之后write在遇到断裂的管道时会返回-1并设置errno为EPIPE程序可以通过检查返回值来进行错误处理而不是突然死亡。捕获信号更精细的控制是捕获信号并自定义处理函数可以在函数中记录日志、清理资源等。4.4 选择管道还是其他IPC管道并非万能。在选择进程间通信方案时需要根据场景权衡。vs. 消息队列消息队列能维护消息边界支持按类型读取并且生命周期与内核相关除非显式删除。适合需要传递结构化、独立消息的场景。管道是字节流需要自己解析。vs. 共享内存共享内存是速度最快的IPC方式因为数据直接映射到进程地址空间无需内核拷贝。但它不提供同步机制需要配合信号量或互斥锁使用编程复杂度高。管道自带同步更安全简单。vs. 套接字Socket套接字功能最强大支持跨网络通信支持TCP/UDP等多种协议。管道只能用于同一台主机上的进程间通信。简单决策指南需要简单、单向、流式的通信且在亲缘进程间用匿名管道。需要简单、单向、流式的通信但在任意进程间用命名管道。需要传递独立、有结构的消息考虑消息队列。需要极高性能、频繁交换大量数据且能处理同步问题考虑共享内存。需要跨网络通信直接用套接字。管道以其极简的API和可靠的阻塞同步机制在脚本编写、进程任务链、以及许多后台服务的内部通信中依然占据着不可替代的一席之地。理解它的原理和脾气是每一位系统级开发者的基本功。下次当你再看到那个竖线|时希望你能会心一笑知道背后是内核在默默地为两个进程搭建一座高效的数据桥梁。

相关新闻

Dify + Celery + Redis 异步节点高可用部署(含K8s Operator配置模板与SLO监控看板)

Dify + Celery + Redis 异步节点高可用部署(含K8s Operator配置模板与SLO监控看板)

第一章:Dify自定义节点异步处理的演进逻辑与2026技术图谱Dify 自定义节点的异步处理机制并非一蹴而就,而是随 LLM 应用架构复杂度提升、可观测性需求增强及边缘推理场景普及而持续演进。早期 v0.5.x 版本依赖同步 HTTP 回调,存在超时阻塞与错…

2026/5/17 10:00:55 阅读更多 →
Windows 11 23H2 环境下 TranslucentTB 任务栏透明失效解决方案

Windows 11 23H2 环境下 TranslucentTB 任务栏透明失效解决方案

Windows 11 23H2 环境下 TranslucentTB 任务栏透明失效解决方案 【免费下载链接】TranslucentTB 项目地址: https://gitcode.com/gh_mirrors/tra/TranslucentTB TranslucentTB 作为一款流行的 Windows 任务栏美化工具,提供了丰富的自定义选项。然而在 Windo…

2026/7/5 10:43:43 阅读更多 →
告别云端依赖:通义千问3-4B-Instruct-2507本地知识库搭建全流程

告别云端依赖:通义千问3-4B-Instruct-2507本地知识库搭建全流程

告别云端依赖:通义千问3-4B-Instruct-2507本地知识库搭建全流程 1. 引言:为什么要在本地搭建知识库? 想象一下这个场景:你正在处理一份公司内部的技术文档,或者分析一份敏感的客户数据。你希望有一个智能助手能帮你快…

2026/5/17 10:00:52 阅读更多 →

最新新闻

番茄小说下载器终极指南:从零开始打造个人数字图书馆的完整解决方案

番茄小说下载器终极指南:从零开始打造个人数字图书馆的完整解决方案

番茄小说下载器终极指南:从零开始打造个人数字图书馆的完整解决方案 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 还在为无法离线阅读番茄小说而烦恼吗&#xff…

2026/7/6 6:57:03 阅读更多 →
PCF8591与PIC18F46K80的信号转换系统设计与优化

PCF8591与PIC18F46K80的信号转换系统设计与优化

1. PCF8591与PIC18F46K80的信号转换系统概述在嵌入式系统开发中,模拟信号与数字信号的相互转换是常见需求。PCF8591作为一款集成了ADC和DAC功能的芯片,配合PIC18F46K80这款高性能8位单片机,可以构建一个灵活的信号处理系统。这个组合特别适合…

2026/7/6 6:57:02 阅读更多 →
参数检验 vs 非参数检验:5种常见场景下的选择决策树与Python/SPSS实现

参数检验 vs 非参数检验:5种常见场景下的选择决策树与Python/SPSS实现

参数检验 vs 非参数检验:5种常见场景下的选择决策树与Python/SPSS实现 数据分析的核心任务之一是通过样本数据推断总体特征。在这个过程中,统计检验方法的选择直接影响结论的可靠性。参数检验和非参数检验作为两大主流方法,各自适用于不同的数…

2026/7/6 6:53:01 阅读更多 →
Python 3.12 文本情感分析实战:基于BERT模型解析《母亲》主题情感倾向

Python 3.12 文本情感分析实战:基于BERT模型解析《母亲》主题情感倾向

Python 3.12 文本情感分析实战:基于BERT模型解析《母亲》主题情感倾向在当代自然语言处理领域,情感分析技术已成为理解文本深层含义的重要工具。本文将带您用Python 3.12和BERT模型,对经典文本《母亲》进行专业级情感倾向解析。不同于传统的人…

2026/7/6 6:53:01 阅读更多 →
LCD 液晶屏驱动时序详解:以 800x480 分辨率为例,配置 VBP/VFP/HBP/HFP 4 个关键参数

LCD 液晶屏驱动时序详解:以 800x480 分辨率为例,配置 VBP/VFP/HBP/HFP 4 个关键参数

LCD 液晶屏驱动时序深度解析:800x480 分辨率实战配置指南1. 液晶显示技术基础与驱动原理液晶显示器(LCD)作为现代电子设备最常用的显示技术之一,其核心在于通过电场精确控制液晶分子的排列状态。当我们在嵌入式系统中使用LCD时&am…

2026/7/6 6:53:01 阅读更多 →
SLO2016与PIC18F87J50在工业自动化中的高效组合

SLO2016与PIC18F87J50在工业自动化中的高效组合

1. SLO2016与PIC18F87J50的黄金组合解析在工业自动化领域,信号传输的稳定性和可靠性直接决定了整个系统的运行质量。SLO2016光电耦合器与PIC18F87J50微控制器的组合,正是为解决这一核心问题而生的经典方案。这套组合拳的独特之处在于:SLO2016…

2026/7/6 6:51:01 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻