Linux内核同步机制:从原子操作到RCU的实战指南

news2026/5/21 1:02:43
1. 项目概述为什么我们需要同步机制想象一下你正在一个繁忙的十字路口指挥交通。如果没有红绿灯和交通规则车辆和行人随意穿行结果必然是混乱、拥堵甚至发生事故。在操作系统的核心——Linux内核中情况惊人地相似。当多个CPU核心就像多辆汽车、中断处理程序像突然冲出来的救护车以及内核线程像执行不同任务的交警同时访问和修改同一块共享数据比如一个链表、一个计数器或一个设备状态时如果没有一套严谨的“交通规则”数据就会损坏系统就会崩溃。这套规则就是内核的同步机制。我处理过不少内核死锁和竞态条件导致的线上故障追查起来往往是因为对同步机制理解不深或者用错了“锁”。今天我们就来深入聊聊Linux内核的同步机制。这不仅仅是理论而是每个想深入理解系统、编写稳健驱动或高性能内核模块的开发者必须掌握的实战技能。无论你是刚接触内核开发的新手还是想系统梳理同步知识的老手这篇文章将从“为什么需要同步”出发拆解各种同步原语的原理、适用场景并分享大量从实际调试和性能优化中得来的“踩坑”经验。2. 同步机制的核心设计思路与选型考量内核同步机制的设计核心目标是在保证数据一致性的前提下尽可能提升并发性能。这听起来像是个“既要又要”的难题内核开发者们为此设计了一整套工具每种工具都有其特定的使用场景和权衡。2.1 竞态条件一切问题的根源竞态条件是指多个执行路径进程、中断、软中断等以不可预测的顺序访问共享数据导致最终结果依赖于执行的时序。一个经典的例子是多个线程同时递增一个共享计数器。如果递增操作读取-修改-写回不是原子的两个线程可能读到相同的旧值各自加一后写回导致最终结果只增加了一次而不是两次。内核中可能引发竞态的场景远比用户态复杂对称多处理SMP多个CPU核心真正并行执行。内核抢占一个进程在内核态执行时可能被更高优先级的进程抢占。中断中断处理程序可以打断正在执行的内核代码。软中断和Tasklet这些延迟执行机制也可能在不可预测的时刻被调度。因此内核同步机制必须能应对所有这些并发源。设计时主要考量几个维度临界区大小需要保护的数据操作范围、睡眠能力在获取锁时能否让出CPU、性能开销以及使用复杂度。2.2 同步原语选型矩阵面对不同的场景没有一把“万能钥匙”。下面这个表格概括了内核主要同步机制的特点和典型使用场景你可以把它当作一个快速选型指南同步机制能否睡眠适用场景性能特点注意事项原子操作否对整型、位进行简单的读写、加减、逻辑操作。开销极小利用CPU的原子指令实现。只能用于简单的数据操作无法保护复杂的代码段。自旋锁否短期持有的锁临界区执行时间短且不允许睡眠如中断上下文。忙等待持有锁时CPU空转。在SMP和多核上至关重要。持有自旋锁时绝对禁止睡眠否则极易导致死锁。读写自旋锁否读多写少的共享数据允许多个读者同时进入。读者并发性好写者具有排他性。要注意读者升级为写者会导致死锁通常不允许。信号量是临界区可能较长或需要睡眠等待的场景。允许有限数量的执行体同时进入。睡眠等待不占用CPU但上下文切换有开销。有计数值可用于资源计数如初始值为5表示5个可用资源。互斥锁是大多数需要互斥访问且可能睡眠的场景。一次只允许一个持有者。比信号量更简洁、高效且支持调试功能如检测死锁。Linux中的mutex是信号量的一个优化特例计数值为1。读写信号量是读多写少且临界区可能较长的场景。类似读写自旋锁但等待者会睡眠。同样需要注意读者到写者的升级问题。完成变量是一个任务等待另一个任务完成特定操作。简单的等待-通知机制。常用于模块初始化、线程启动同步等。顺序锁否读非常频繁写极少且读者能容忍读到稍旧的数据。读者完全无锁仅读序列号性能极高。写者需要独占。读者在读取前后需要检查序列号是否变化如果变化则重试。RCU读-复制-更新是仅对写者有限制读极多、写极少的数据结构如路由表。读者的开销几乎为零无锁、无原子操作、无内存屏障。写者开销大需要延迟释放旧数据。理解和使用门槛较高。注意这个选型不是绝对的。例如在中断处理程序中你只能使用自旋锁或原子操作因为中断上下文不能睡眠。而在可能睡眠的进程上下文中互斥锁通常是比信号量更现代和推荐的选择。3. 核心同步原语深度解析与实操要点了解了全景图我们深入看看几个最常用、也最容易用错的核心原语。我会结合内核源码片段以5.x版本为例和实际案例来解释。3.1 自旋锁内核中的“忙等交警”自旋锁的设计哲学是如果锁被占用请求者就原地“自旋”循环检查直到锁被释放。这避免了进程切换的开销适用于锁持有时间非常短的场景。#include linux/spinlock.h // 定义和初始化 spinlock_t my_lock; spin_lock_init(my_lock); // 加锁 spin_lock(my_lock); // 临界区代码... // 解锁 spin_unlock(my_lock);关键点与避坑指南中断安全性如果你的临界区可能被中断处理程序访问并且该中断处理程序也会获取同一把锁你必须使用spin_lock_irqsave()和spin_unlock_irqrestore()。这会在加锁的同时禁用本地CPU的中断并保存中断状态解锁时恢复。unsigned long flags; spin_lock_irqsave(my_lock, flags); // 临界区 spin_unlock_irqrestore(my_lock, flags);为什么假设CPU0持有锁此时发生中断CPU0转去执行中断处理程序。如果该处理程序也尝试获取同一把锁它就会在CPU0上永远自旋下去因为锁的持有者被中断的进程无法继续执行来释放锁。这就是发生在单个CPU上的死锁。spin_lock_irqsave通过禁用中断杜绝了这种可能。绝对禁止睡眠在持有自旋锁的临界区内不能调用任何可能引起睡眠的函数如kmalloc(GFP_KERNEL)、copy_from_user、mutex_lock等。因为睡眠会导致进程切换其他CPU可能一直在自旋等待这把锁浪费大量CPU时间甚至可能引发死锁。锁的粒度锁保护的是数据而不是代码。要尽量减小临界区范围只把真正需要串行化的数据访问包起来。过大的临界区会严重损害并发性能。实操心得在驱动开发中保护设备寄存器或内部状态结构体时自旋锁非常常见。我总是会问自己这个临界区会被中断处理程序访问吗如果会毫不犹豫地用_irqsave版本。3.2 互斥锁可睡眠的“房间钥匙”互斥锁是信号量的一种特例计数值为1但它接口更清晰且内嵌了更多的调试和死锁检测功能如CONFIG_DEBUG_MUTEXES。#include linux/mutex.h // 定义和初始化 static DEFINE_MUTEX(my_mutex); // 静态初始化 // 或者 struct mutex my_mutex; mutex_init(my_mutex); // 动态初始化 // 加锁 mutex_lock(my_mutex); // 临界区代码这里可以安全地睡眠 // 解锁 mutex_unlock(my_mutex);关键点与避坑指南递归上锁Linux内核的mutex不支持递归上锁。即同一个任务不能对已经持有的互斥锁再次调用mutex_lock这会导致自死锁。如果你需要递归锁可能需要重新设计你的锁层次结构或者使用其他机制。锁的持有者mutex明确记录了持有它的任务。这在调试时非常有用DEBUG_MUTEXES会利用这个信息也使得实现“优先级继承”等实时性特性成为可能。中断上下文互斥锁不能用于中断上下文因为mutex_lock可能睡眠。mutex_lock_interruptible这是一个变体如果获取锁时被信号打断它会返回-EINTR。这在需要处理用户信号如CtrlC的代码中很有用。if (mutex_lock_interruptible(my_mutex)) { // 被信号打断处理错误 return -ERESTARTSYS; }实操心得对于大部分内核中需要互斥且可能睡眠的场景mutex已经取代了信号量成为首选。它的API更清晰错误检查也更完善。在编写新的内核代码时除非需要信号量的计数功能否则优先考虑mutex。3.3 读写锁区分读者与写者当数据结构读远多于写时使用普通的互斥锁会不必要地串行化所有读操作降低性能。读写锁允许多个读者同时进入但写者是排他的。自旋锁版本(rwlock_t)rwlock_t my_rwlock; read_lock(my_rwlock); // 读操作... read_unlock(my_rwlock); write_lock(my_rwlock); // 写操作... write_unlock(my_rwlock);信号量版本(struct rw_semaphore)struct rw_semaphore my_rwsem; down_read(my_rwsem); // 读操作... up_read(my_rwsem); down_write(my_rwsem); // 写操作... up_write(my_rwsem);关键点与避坑指南“写者饥饿”与“读者饥饿”这是读写锁的经典权衡。如果读者源源不断写者可能永远无法获得锁写者饥饿。内核的读写锁实现通常倾向于避免读者饥饿但这意味着在持续有读负载的情况下写者可能会被延迟。你需要根据业务特点评估。锁升级与降级锁升级先持有读锁再尝试获取写锁在内核的标准读写锁中会导致死锁因为写锁需要等待所有读锁释放而你自己就持有一个读锁。锁降级先持有写锁再降为读锁通常是安全的并且有些实现如rw_semaphore通过downgrade_write()函数明确支持。选择自旋还是睡眠规则和之前一样临界区短且不允许睡眠如中断上下文用自旋版本(rwlock_t)临界区长或可能睡眠用信号量版本(rw_semaphore)。实操心得不要盲目使用读写锁。只有在有明确的性能分析数据表明读竞争是瓶颈时才考虑将互斥锁替换为读写锁。因为读写锁的实现比互斥锁更复杂在无竞争或写多读少的场景下其开销可能反而更大。4. 高级同步机制RCU与顺序锁当性能要求达到极致时就需要更精巧的同步机制。4.1 RCU读侧零开销的“魔法”RCU的核心思想是写者复制一份要修改的数据更新副本然后用一个原子指针替换指向旧数据的指针。读者总是通过指针访问数据因此读操作完全不需要锁、原子操作或内存屏障。旧数据的回收会延迟到所有可能正在读它的读者都退出后才进行。使用模式// 读者侧极其快速 rcu_read_lock(); p rcu_dereference(global_ptr); // 安全地访问 p-field1, p-field2... rcu_read_unlock(); // 写者侧 new_ptr kmalloc(...); // 初始化或复制数据到 new_ptr old_ptr global_ptr; rcu_assign_pointer(global_ptr, new_ptr); // 发布新数据 synchronize_rcu(); // 等待所有现有读者退出 kfree(old_ptr); // 安全释放旧数据关键点与避坑指南适用范围RCU非常适合保护经常被读、但很少被写的指针型数据结构。链表是一个经典用例。它不适合保护需要频繁更新或数据结构非指针的场景。写者开销synchronize_rcu()或call_rcu()的代价很高它需要等待一个“宽限期”所有CPU都至少经历一次上下文切换。写者路径必须能够承受这个延迟。内存屏障rcu_dereference()和rcu_assign_pointer()内部包含了必要的内存屏障确保在弱内存序的体系结构上也能正确工作。这是RCU正确性的基石不要试图绕过它们。睡眠限制在rcu_read_lock()和rcu_read_unlock()构成的读侧临界区内可以睡眠但不太常见因为这会延长宽限期。实操心得RCU是内核中最复杂同步机制之一。除非你维护的子系统确实有极端的读性能需求如网络栈的路由表、虚拟文件系统的目录项缓存否则建议先精通其他锁机制。使用RCU时一定要理解其“发布-订阅”和“延迟回收”的语义并善用内核提供的CONFIG_DEBUG_OBJECTS_RCU_HEAD等调试选项。4.2 顺序锁为读者追求极致速度顺序锁通过一个序列计数器来工作。写者在修改数据前将序列号加1修改后再加1变成偶数-奇数-偶数。读者在读取数据前后读取序列号如果前后序列号相同且为偶数说明读取过程中没有写操作干扰数据有效。seqlock_t my_seqlock; unsigned int seq; do { seq read_seqbegin(my_seqlock); // 读取共享数据... } while (read_seqretry(my_seqlock, seq)); write_seqlock(my_seqlock); // 修改共享数据... write_sequnlock(my_seqlock);关键点与避坑指南读者容忍旧数据这是使用顺序锁的前提。读者可能读到正在被修改的、不一致的数据但通过重试机制最终能读到一致的数据。如果你的读者要求总是看到绝对一致的最新数据顺序锁不适用。写者独占写操作是互斥的并且写锁是基于自旋锁实现的所以写者临界区必须短且不能睡眠。适用场景适用于写非常少但读极其频繁且读操作可以容忍瞬时不一致的场景。例如内核中jiffies系统时间戳的更新就使用了顺序锁。实操心得顺序锁的使用场景比RCU更窄。在考虑它之前先确认你的数据是否真的是“几乎只读”并且读者是否真的可以接受偶尔读到“正在更新中”的数据。对于系统状态统计、某些频率更新不高的硬件寄存器读取它可能是个好选择。5. 内存屏障看不见的同步墙在多核CPU弱内存模型的体系结构如ARM、PowerPC上编译器和处理器为了性能可能会对内存访问指令进行重排序。这可能导致我们精心设计的锁机制失效。内存屏障就是用来强制约束这种重排序的。为什么需要内存屏障考虑一个简单的标志位通信// CPU 0 data 123; flag 1; // 表示数据已就绪 // CPU 1 while (!flag) ; // 等待数据就绪 printk(“%d”, data);在没有内存屏障的情况下CPU 0的写入data和flag可能被其他CPU观测到顺序颠倒即先看到flag1后看到data123。这样CPU 1就可能读到未初始化的data值。内核提供的屏障通用屏障mb()(读/写屏障) 和barrier()(编译时屏障)。写屏障wmb()确保屏障前的所有写操作先于屏障后的写操作被其他CPU看到。读屏障rmb()确保屏障前的所有读操作先于屏障后的读操作完成。优化屏障barrier()阻止编译器跨屏障重排指令但不对CPU硬件产生直接影响。关键点与避坑指南锁隐含了屏障spin_lock()/spin_unlock(),mutex_lock()/mutex_unlock()等锁操作函数内部已经包含了必要的内存屏障。在持有锁的情况下访问共享数据通常不需要额外添加屏障。原子操作与屏障像atomic_t的操作通常是原子的但未必包含完整的屏障语义。例如atomic_inc()可能不保证其前后的内存操作顺序。如果需要严格的顺序要使用带屏障版本的原子操作如atomic_inc_return()的某些实现或显式使用smp_mb__before_atomic()/smp_mb__after_atomic()。无锁编程的必需品当你进行无锁编程如使用RCU或自己实现无锁数据结构时必须非常小心地使用内存屏障来保证正确的可见性和顺序。这是无锁编程中最容易出错的地方之一。实操心得对于大部分使用标准内核同步原语的开发者你不需要直接使用内存屏障。但当你开始涉足高性能无锁算法、驱动程序中与设备进行严格的内存顺序通信、或者阅读内核中那些精妙的底层代码时理解内存屏障就至关重要。我的建议是除非你非常清楚自己在做什么并且有充分的理由否则尽量使用内核提供的、已经包含了正确屏障语义的高级同步接口。6. 死锁预防与调试实战同步机制用不好最直接的后果就是死锁——两个或多个执行路径互相等待对方持有的资源导致系统卡死。6.1 常见的死锁场景递归死锁任务试图获取一个它已经持有的锁。互斥锁明确禁止这个操作会报错但自旋锁不会会导致永久自旋。AB-BA死锁// CPU 0 spin_lock(lock_A); spin_lock(lock_B); // CPU 1 spin_lock(lock_B); spin_lock(lock_A);两个任务以相反的顺序获取两把锁。在SMP系统上这可能发生。中断上下文死锁如前所述在单CPU上进程持有锁时被中断中断处理程序又试图获取同一把锁。睡眠导致的死锁在持有自旋锁时睡眠可能导致其他等待该锁的CPU空转也可能因睡眠引发复杂的锁依赖链最终形成环路。6.2 死锁预防策略固定锁顺序这是解决AB-BA死锁最有效的方法。为系统中所有的锁定义一个全局的获取顺序例如锁A必须总是在锁B之前获取。在大型项目中这需要良好的文档和代码审查来维护。使用mutex的调试功能开启CONFIG_DEBUG_MUTEXES内核会跟踪锁的依赖关系并在可能发生死锁时输出警告信息如“possible recursive locking detected”。持有锁时禁止中断在可能被中断共享的锁上使用spin_lock_irqsave()。避免在持有锁时调用可能获取其他锁的复杂函数尽量让临界区内的操作简单、可预测。使用lockdepLinux内核有一个强大的锁依赖跟踪器lockdep(CONFIG_PROVE_LOCKING)。它会动态构建锁的获取顺序图一旦检测到潜在的锁顺序违规即使当前运行没有触发死锁就会抛出警告。这是内核开发者的神器。6.3 调试死锁的实战技巧当系统发生死锁时你可能看到系统无响应或者在内核日志中找到“INFO: task xxx blocked for more than 120 seconds”这样的信息。获取堆栈信息如果系统还有响应可以通过SysRq键AltSysRqt或echo t /proc/sysrq-trigger让内核打印所有任务的堆栈。或者查看/proc/pid/stack获取特定任务的堆栈。分析堆栈在堆栈信息中寻找阻塞在__schedule()或schedule()附近并且显示正在等待某个锁如mutex_lock、down_interruptible的任务。查看是哪些锁以及谁持有着它们。检查lockdep报告如果开启了lockdep在系统启动或运行过程中关注内核日志中lockdep输出的警告。这些警告往往直接指出了锁顺序问题。使用ftrace的锁跟踪可以开启ftrace的锁事件跟踪观察锁的获取和释放序列帮助定位问题。实操心得预防远胜于治疗。在新代码中严格遵守锁顺序积极使用lockdep进行测试。一旦线上发生死锁保存第一现场如SysRq输出、内核日志至关重要。对于复杂的死锁分析堆栈就像破案需要耐心梳理每个任务持有的锁和等待的锁画出依赖图就能找到环路了。7. 性能考量与同步机制的选择艺术选择同步机制本质是在正确性和性能之间做权衡。以下是一些指导原则评估临界区大小操作是几个指令如递增计数器还是涉及复杂的数据结构遍历频率被访问的频率有多高是读多还是写多睡眠可能性操作中是否会分配内存、访问用户空间、或等待其他事件选择路径极小、无睡眠、高频首选原子操作或顺序锁如果读者可容忍旧数据。短小、无睡眠使用自旋锁。注意中断安全性。可能睡眠、互斥访问使用互斥锁。可能睡眠、读多写少使用读写信号量。读极多、写极少、数据结构为指针深入评估RCU。保护整型或位使用原子操作。性能测试与 profiling理论分析很重要但最终要用数据说话。使用perf、ftrace或lockstat等工具来测量锁的争用情况。lockstat可以告诉你自旋锁的自旋等待时间、互斥锁的睡眠等待时间。perf lock可以分析锁的争用和持有时间。 如果发现某个锁的争用非常激烈contention值很高就需要考虑能否缩小临界区能否拆分锁用多个小锁代替一个大锁能否改变数据结构或算法来减少共享无锁数据结构的思考在极端性能要求的场景下可以考虑无锁数据结构如无锁队列。但这会极大地增加代码的复杂性和验证难度。除非有压倒性的性能证据并且团队有相应的能力否则应谨慎使用。内核中的kfifo单生产者单消费者场景是一个相对简单的无锁环状缓冲区例子。内核同步是一个深邃且实践性极强的领域。从最基础的原子操作到精巧的RCU每一层工具都是为了解决特定场景下的并发问题。理解它们的原理、代价和适用边界是写出正确、高效、可靠内核代码的关键。在实际编码中我倾向于从最保守、最简单的锁如mutex开始确保正确性然后通过性能剖析再有针对性地进行优化和替换。记住过早优化是万恶之源在同步问题上尤其如此。一把用错的锁带来的不仅仅是性能损失更是系统稳定性的噩梦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2629928.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…