当前位置: 首页 > news >正文

arm linux下的读写信号量rw_semphore的实现

本文基于arm linux 5.10来介绍内核中使用的读写信号量rw remphore的实现代码。

内核中信号量结构体struct rw_semaphore的定义在include/linux/rwsem.h

32位architectures下,结构体struct rw_semaphore中的count的使用如下:

先来看信号量的定义和初始化函数和宏:

宏DECLARE_RWSEM()定义了一个读写信号量,并初始化count为0.

如果我们已经定义了信号量变量,要初始化它,可以使用init_rwsem()或直接使用__init_rwsem(), 它们的定义如下:

init_rwsem()和__init_rwsem()他们初始化信号量计数count也是为0.

读写信号量,运行多个读,读与写互斥,写只能有一个。

先看读信号量获取: down_read().

down_read()先调用__down_read_trylock()去上锁, 如果trylock()上锁失败(返回0), 再调用__down_read()去上锁。

先来看__down_read_trylock().

__down_read_trylock() -> atomic_long_try_cmpxchg_acquire() -> atomic_try_cmpxchg_acquire()

这个atomic_try_cmpxchg_acquire()在include/linux/atomic-fallback.h中定义,它有两个定义处,用哪个依赖于对应architecture的atomic.h中定义。

我们来看armv7下的atomic.h中是否定义了atomic_try_cmpxchg_relaxed.

所以,在armv7下,atomic_try_cmpxchg_relaxed没有#define.故,__down_read_trylock() -> atomic_long_try_cmpxchg_acquire() -> atomic_try_cmpxchg_acquire()

这个atomic_try_cmpxchg_acquire()在include/linux/atomic-fallback.h中926行定义,如下:

故,atomic_try_cmpxchg_acquire() -> atomic_cmpxchg_acquire()。

atomic_cmpxchg_acquire() 定义如下:

故, atomic_cmpxchg_acquire() -> atomic_cmpxchg_relaxed().

所以,__down_read_trylock() -> atomic_long_try_cmpxchg_acquire() ->

atomic_try_cmpxchg_acquire() -> atomic_cmpxchg_acquire() -> atomic_cmpxchg_relaxed(),

atomic_cmpxchg_relaxed()定义在arch/arm/include/asm/atomic.h, 如下:

117行:加载信号量计数 sem->count.counter.

118行:清零res.

119行:比较信号量计数值和参数old的大小.

120行:信号量计数值和参数old相等,则将参数new更新到信号量计数。

126行:返回信号量计数更新前的值。

从实现代码看出,__down_read_trylock()是判断信号量计数是否为初值RWSEM_UNLOCKED_VALUE(0), 是的话,则将read计数设置为1(就是1<<8)。

当__down_read_trylock()失败时,则调用__down_read().

__down_read()先调用rwsem_read_trylock().

__down_read() -> rwsem_read_trylock() -> atomic_long_add_return_acquire() ->

atomic_add_return_acquire() -> atomic_add_return_relaxed().

atomic_add_return_relaxed()定义如下:

65行:加载信号量计数sem->count.counter

66行:sem->count.counter + (1 << 8)

67行:新值更新到sem->count.counter

74行:返回sem->count.counter新值。

所以,__down_read()-> rwsem_read_trylock()就是将信号量读计数+1.

rwsem_read_try_lock()拿到更新read计数后的新值时,判断锁是否存在写者或者等待者waiter(279行),存在写者或者等待者waiter时,返回0;否则返回1.

当信号量有写者时,__down_read() –> rwsem_down_read_slowpath().

rwsem_down_read_slowpath()将当前task放入信号量等待队列sem->wait_list中,并设置为TASK_UNINTERRUPTIBLE状态,同时,将信号量计数sem->count减1.

好了,读信号量获取介绍完了,下面介绍读信号量释放: up_read().

up_read() -> __up_read() -> atomic_long_add_return_release() -> atomic_add_return_release() ->

atomic_add_return_relaxed()

atomic_add_return_relaxed() 定义如下:

可见,up_read() -> __up_read()就是将读计数-1。

__up_read()将读计数减1后,判断是等待队列是否有等待者wait_list,有则调用rwsem_wake()将去唤醒。如果等待队列中第一个是写占有请求,则唤醒这个写占有请求者去占有信号量;如果等待队列中第一个不是写等待者,则优先将等待队列中读请求者全部唤醒(最多0x100个)

信号量读操作介绍完了,来看看信号量写。

写信号量获取: down_write().

down_write()先调用__down_write_trylock()获取信号量,如果失败(返回0),则再调用__down_write().

atomic_cmpxchg_acquire() 定义如下:

所以,down_write() -> __down_write_trylock() -> atomic_long_try_cmpxchg_acquire() ->

atomic_try_cmpxchg_acquire() -> atomic_cmpxchg_acquire() -> atomic_cmpxchg_relaxed().

atomic_cmpxchg_relaxed()定义在arch/arm/include/asm/atomic.h,

如下:

117行:加载信号量计数 sem->count.counter.

118行:清零res.

119行:比较信号量计数值和参数old的大小.

120行:信号量计数值和参数old相等,则将参数new更新到信号量计数。

126行:返回信号量计数更新前的值。

down_write() -> __down_write_trylock()就是先判断信号量是否为初值RWSEM_UNLOCKED_VALUE(0)。是的话,则设置信号量count为RWSEM_WRITER_LOCKED (1<<0). 否则__down_write_trylock()就是获取信号量失败,down_write()则调用__down_write()去获取写信号量。

__down_write()先调用atomic_long_try_cmpxchg_acquire(), 这个操作和

__down_write_trylock()一样。

atomic_cmpxchg_acquire() 定义如下:

down_write() -> __down_write() -> atomic_long_try_cmpxchg_acquire() ->

atomic_try_cmpxchg_acquire() -> atomic_cmpxchg_acquire() -> atomic_cmpxchg_relaxed().

atomic_cmpxchg_relaxed()定义在arch/arm/include/asm/atomic.h, 如下:

117行:加载信号量计数 sem->count.counter.

118行:清零res.

119行:比较信号量计数值和参数old的大小.

120行:信号量计数值和参数old相等,则将参数new更新到信号量计数。

126行:返回信号量计数更新前的值。

down_write() -> __down_write()就是判断信号量是否为初值RWSEM_UNLOCKED_VALUE(0)。是的话,则设置信号量count为RWSEM_WRITER_LOCKED (1<<0),否则就是获取信号量失败,则进入rwsem_down_write_slowpath().

1166-1175行:将当前写信号量请求者添加到等待队列sem->wait_list.

1178-1196行:如果当前写信号量请求者不是第一个等待者,则唤醒等待队列前面的task,

读等待者优先。

1207行:设置当前有等待者flag: RWSEM_FLAG_WAITERS

1212行:设置当前进程状态为不可中断休眠状态TASK_UNINTERRUPTILE。

1214行:调用rwsem_try_write_lock(), 尝试去lock信号量。

1238行:重新调度,让出cpu。

好了,写信号量获取down_write()介绍完了,来介绍最后一个写信号量释放: up_write().

up_write() -> __up_write() -> atomic_long_fetch_add_release()

up_write() -> __up_write() -> atomic_long_fetch_add_release() -> atomic_fetch_add_release() ->

atomic_featch_add_relaxed()

atomic_featch_add_relaxed()的定义如下:

86行:加载sem->count.counter

87行:sem->count.counter + i

88行:保存sem->count.counter + i到sem->count.counter。

95行:返回值result为sem->count.counter更新前的值。

故,up_write() -> __up_write()就是删除write_lock, 即写者不再占有信号量。

当写者释放信号量时,如果该信号量有等待者waiters, 则调用rwsem_wake()去唤醒第一个写等待者;如果第一个不是写等待者,则优先唤醒等待队列中所有读等待者(最多0x100个)。

这里的唤醒没有reader优先,和rwsem_down_write_slowpath()不一样。

好了,我们讲解完了读写信号量。现在总结一下:

  1. 当信号量当前被读者占有时,允许其他task读lock, 每lock一次,读计数+1,读lock次数不限制(当然在计数器不溢出范围内),也就是允许多个读存在。此时写占有请求被阻止,写占有请求者task将被放入等待队列sem->wait_list. 这之后来的读请求,都将被放入等待队列(因为被设置了waiters flag)。当信号量所有读占有者释放信号量时,写占有请求者task将被唤醒,去占有信号量。

  1. 当信号量当前被写者占有时,任何其他读请求者或写请求者,都将被组织,请求者被放入等待队列sem->wait_list.当信号量写占有者释放信号量时,如果有信号量占有请求,则去做唤醒动作。如果等待队列第一个是写占有请求,则将其唤醒去占有信号量。如果等待队列第一个不是写占有请求,则优先将所有读占有请求者(最多0x100个)唤醒去占有信号量。

相关文章:

arm linux下的读写信号量rw_semphore的实现

本文基于arm linux 5.10来介绍内核中使用的读写信号量rw remphore的实现代码。 内核中信号量结构体struct rw_semaphore的定义在include/linux/rwsem.h 32位architectures下&#xff0c;结构体struct rw_semaphore中的count的使用如下&#xff1a; 先来看信号量的定义和初始化…...

搭建主从DNS、nfs、nginx

任务需求&#xff1a; 客户端通过访问 www.nihao.com 后&#xff0c;能够通过 dns 域名解析&#xff0c;访问到 nginx 服务中由 nfs 共享的首页文件&#xff0c;内容为&#xff1a;Very good, you have successfully set up the system. 各个主机能够实现时间同步&#xff0c;…...

Qt6+QML实现Windows屏幕录制

前言 Qt6提供了更丰富的多媒体支持类&#xff0c;使用Qt6 QMediaCaptureSession、QScreenCapture、QMediaRecorder&#xff0c;来实现一个屏幕录制的demo&#xff0c;其中QScreenCapture 最低版本 Qt6.5。支持录制的清晰度设置&#xff0c;选择视频保存位置&#xff0c;UI使用…...

python二级每日十题(1)

\ 第一题,在Python中&#xff0c;变量名的命名规则&#xff1a;以字母或下划线开头&#xff0c;后面跟字母、下划线和数字&#xff1b;不能以数字开头.故选c项,博主正确 缩进&#xff1a;在逻辑行首的空白&#xff08;空格和制表符&#xff09;用来决定逻辑行的缩进层次&…...

记录一次truncate导致MySQL夯住的故障

目录 环境信息&#xff1a; 故障描述&#xff1a; 处理过程&#xff1a; 原理分析&#xff1a; show processlist结果中的system lock含义&#xff1a; truncate原理&#xff1a; 1. TRUNCATE 的执行流程 2、TRUNCATE 表导致数据库夯住的原因 3、 TRUNCATE 表导致…...

Java Web应用程序实现用户登录、学生信息管理和验证码验证以及页面跳转等基本功能(IDEA)含(Ajax、JSTL)

一、具体框架以及代码功能的展示&#xff1a; 1. 文件结构 web03: 项目根目录。 src: 包含Java源代码。 cn.lvb: 主包。 bean: 包含实体类&#xff0c;如 Book 和 Student。 controller: 包含处理HTTP请求的Servlet类&#xff0c;如 DoLogin, Index, StuList1, VerifyCode。 …...

【Mybatis-plus】在mybatis-plus中 if test标签如何判断 list不为空

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

MySQL 事务(Transaction)详解

MySQL 事务&#xff08;Transaction&#xff09;详解 1. 什么是事务&#xff1f; 事务&#xff08;Transaction&#xff09;是一组要么全部执行&#xff0c;要么全部回滚的 SQL 语句&#xff0c;用于保证数据一致性。事务一般用于银行转账、订单支付等操作&#xff0c;确保多个…...

Redis 知识点梳理

第一章 NoSQL数据库发展历史简介 1、 Web的历史发展历程 web1.0时代简介 web 1.0是以编辑为特征&#xff0c;网站提供给用户的内容是网站编辑进行编辑处理后提供的&#xff0c;用户阅读网站提供的内容这个过程是网站到用户的单向行为web1.0时代的代表站点为新浪&#xff0c;…...

github上传操作简单说明

前期准备 0.下载git&#xff08;如果已经有了就不用了&#xff09; 1.在GitHub上新建一个存储库 2.先在本地创建一个目录作为本地库目录&#xff0c;在目录里打开git bash进行上传 上传过程 echo "# Garbled_repair" >> README.md 作用&#xff1a;创建一个…...

在 ASP .NET Core 9.0 中使用 Scalar 创建漂亮的 API 文档

示例代码&#xff1a;https://download.csdn.net/download/hefeng_aspnet/90407900 Scalar 是一款可帮助我们为 API 创建精美文档的工具。与感觉有些过时的默认 Swagger 文档不同&#xff0c;Scalar 为 API 文档提供了全新而现代的 UI。其简洁的设计让开发人员可以轻松找到测试…...

针对 pdf.mjs 文件因 MIME 类型错误导致的 Failed to load module script 问题解决方案

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of “application/octet-stream”. Strict MIME type checking is enforced for module scripts per HTML spec. pdf.mjs 这种问题该如何处理 nginx 针对 pdf.…...

Flink介绍与安装

Apache Flink是一个在有界数据流和无界数据流上进行有状态计算分布式处理引擎和框架。Flink 设计旨在所有常见的集群环境中运行&#xff0c;以任意规模和内存级速度执行计算。 一、主要特点和功能 1. 实时流处理: 低延迟: Flink 能够以亚秒级的延迟处理数据流&#xff0c;非常…...

《双指针算法指南:LeetCode 经典题解(C++实现)》

《双指针算法指南&#xff1a;LeetCode 经典题解&#xff08;C实现&#xff09;》 —— 从快慢指针到对撞指针&#xff0c;刷题效率提升 200%&#xff01; 常⻅的双指针有两种形式&#xff0c;⼀种是对撞指针&#xff0c;⼀种是左右指针。 对撞指针&#xff1a; ⼀般⽤于顺…...

kaggle上经典泰坦尼克项目数据分析探索

之前了解在kaggle上这个项目很火&#xff0c;最近想要加强一下python数据分析&#xff0c;所以在kaggle上找到这个项目进行学习探索&#xff0c;下面是将一些学习资料以及过程整理出来。 一、首先我们了解一下项目背景以及如何找到这个项目。 kaggle项目地址: https://www.k…...

【深度学习】多目标融合算法(五):定制门控网络CGC(Customized Gate Control)

目录 一、引言 二、CGC&#xff08;Customized Gate Control&#xff0c;定制门控网络&#xff09; 2.1 技术原理 2.2 技术优缺点 2.3 业务代码实践 2.3.1 业务场景与建模 2.3.2 模型代码实现 2.3.3 模型训练与推理测试 2.3.4 打印模型结构 三、总结 一、引言 上一…...

Ubuntu上查看GPU使用情况并释放内存

先用nvidia-smi查看GPU当前使用情况 再用fuser 命令查找对应显卡上占用 GPU 的进程 最后查到了用kill -9强制杀掉进程&#xff08;PID&#xff09;即可...

大数据学习栈记——HBase安装

本文介绍大数据技术中流行的非关系型数据库HBase的安装&#xff0c;操作系统&#xff1a;Ubuntu24.04 安装Zookeeper 安装HBase前需要先安装Zookeeper&#xff0c;HBase使用Zookeeper作为其分布式协同服务&#xff0c;存储了HBase集群的元数据信息&#xff0c;并提供了分布式…...

[入门]NUC13配置Ubuntu20.04详细步骤

文章目录 1. 安装Ubuntu20.041.1 制作系统启动盘1.1.1 下载镜像文件1.1.2 配置启动盘 1.2 安装内存条、硬盘1.3 安装系统 2. 网卡驱动配置2.1 关闭安全启动2.2 安装intel官方网卡驱动backport2.2.1 第四步可能会出现问题 2.3 ubuntu官方的驱动2.4 重启 3. 软件安装3.1 录屏软件…...

【实战指南】用MongoDB存储文档和图片等大文件(Java实现)

一、前言 在现代应用开发中,经常需要处理和存储大量的文档、图片等大文件。传统的关系型数据库在处理这类大文件时,往往会面临性能瓶颈、存储成本高等问题。而 MongoDB 作为一款流行的 NoSQL 数据库,提供了 GridFS 规范,能够很好地解决大文件存储的问题。GridFS 可以将大文…...

使用Gitee Go流水线部署个人项目到服务器指南

使用Gitee Go流水线部署个人项目到服务器指南 前言&#xff01;&#xff01;&#xff01; 本文解决的问题&#xff1a; 你有一台ECS服务器&#xff0c;你在上面部署了一个Java服务也就是一个jar&#xff0c;你觉着你每次手动本地打包&#xff0c;上传&#xff0c;在通过命令去…...

使用Three.js渲染器创建炫酷3D场景

引言 在当今数字化的时代&#xff0c;3D图形技术正以其独特的魅力在各个领域掀起波澜。从影视制作到游戏开发&#xff0c;从虚拟现实到网页交互&#xff0c;3D场景以其强烈的视觉冲击力和沉浸式的体验&#xff0c;成为了吸引用户、传达信息的重要手段。而Three.js&#xff0c;…...

Spring Boot 集成 Elasticsearch怎样在不启动es的情况下正常启动服务

解释 在spingboot 集成es客户端后&#xff0c;每当服务启动时&#xff0c;服务默认都会查看es中是否已经创建了对应的索引&#xff0c;如果没有索引则创建。基于上面的规则我们可以通过配置不自动创建索引来达到在没有es服务的情况下正常启动服务。 解决办法 在entity类的Docu…...

明远智睿SD2351核心板:多接口融合,破解边缘计算难题

在边缘计算领域&#xff0c;明讯智睿SD2351核心板凭借丰富的接口资源与异构计算架构&#xff0c;成为工业网关与智能终端的理想选择。硬件配置升级 :处理器:四核Cortex-A35&#xff0c;256KB L2缓存&#xff0c;动态调频降低功耗;存储性能:emMC 5.0 HS400模式读写速度提升40%&a…...

xampp安装教程与配置

一、安装 XAMPP &#xff08;一&#xff09;下载 访问官网&#xff1a;打开浏览器&#xff0c;访问 XAMPP 官方网站&#xff08;https://www.apachefriends.org/zh_cn/index.html&#xff09;。 选择版本&#xff1a;根据你的操作系统&#xff08;Windows、macOS 或 Linux&am…...

设计模式之单例模式(Singleton Pattern)

单例模式&#xff08;Singleton Pattern&#xff09;是一种常用的设计模式&#xff0c;确保一个类只有一个实例&#xff0c;并提供一个全局访问点。单例模式在许多场景中非常有用&#xff0c;例如配置管理、日志记录、线程池等。 ### **1. 单例模式的特点** 1. **唯一实例**&a…...

Androidstudio实现引导页文字动画

文章目录 1. 功能需求2. 代码实现过程1. 编写布局文件2. 实现引导页GuideActivity 3. 总结4. 效果演示5. 关于作者其它项目视频教程介绍 1. 功能需求 1、引导页具有两行文字&#xff08;“疫情在前”和“共克时艰”&#xff09;&#xff0c;和向上的 图标。 2、进入【引导页】…...

【linux】线程概念与控制

引言 当现代CPU的晶体管密度逼近物理极限&#xff0c;多核架构已成为突破性能瓶颈的必由之路。在这个计算密集型任务与异步IO需求并行的时代&#xff0c;多线程编程不再是可选项&#xff0c;而是开发者必须掌握的核心技能。Linux作为承载着全球90%云计算负载的操作系统&#xf…...

Cesium 自定义路径导航材质

cesium 自定义路径导航纹理图片随便更换&#xff0c;UI 提供设计图片即可达到效果&#xff1b; 打开小马的weix 关注下 搜索“技术链” 回复关键词《《路径》》获取原始代码&#xff1b; 拿到就能用轻松解决&#xff01;帮忙点个关注吧&#xff01;...

用 pytorch 从零开始创建大语言模型(五):预训练无标注数据

用 pytorch 从零开始创建大语言模型&#xff08;五&#xff09;&#xff1a;预训练无标注数据 5 预训练无标注数据5.1 评估文本生成模型5.1.1 使用 GPT 生成文本5.1.2 计算文本生成损失5.1.3 计算训练集和验证集的损失 5.2 训练 LLM5.3 解码策略以控制随机性5.3.1 温度缩放&am…...

[AI速读]混合验证方案:如何高效解决RISC-V向量扩展的验证难题

RISC-V作为一种开源指令集架构,近年来在AI和高性能计算领域备受关注。其向量扩展(RVV)为处理并行数据提供了强大的支持,但复杂的异常处理和冒险检测机制也带来了验证上的巨大挑战。本文将结合一篇技术论文,解析一种混合验证方案,帮助开发者更高效地解决RVV的验证问题。 一…...

模型空间、图纸空间、布局(Layout)之间联系——CAD c#二次开发

在 AutoCAD 的二次开发中&#xff0c;**模型空间&#xff08;Model Space&#xff09;**、**图纸空间&#xff08;Paper Space&#xff09;** 和 **布局&#xff08;Layout&#xff09;** 是三个核心概念&#xff0c;它们的关系及开发中的操作逻辑如下&#xff1a; --- 1. 模…...

Linux 日常开发常用命令(解释-全)

帮助类 #查看cd命令的帮助信息 [rootcentos100 ~] help cd # 查看网卡配置信息 [rootcentos100 ~] ifconfig # 检测到目标主机是否连接正常 [rootcentos100 ~] ping IP地址[rootcentos100 ~] ssh [-p port] userremote #远程登录user 是在远程机器上的用户名&#xff0c;如果…...

数据库监控:确保业务连续性和用户体验

在数字化时代&#xff0c;数据库作为企业的数据心脏&#xff0c;其重要性不言而喻。无论是交易系统、客户关系管理系统&#xff0c;还是数据分析平台&#xff0c;都离不开数据库的支撑。然而&#xff0c;数据库的运行状态和性能直接影响着企业的业务连续性和用户体验。因此&…...

Java面试黄金宝典9

1. Redis 持久化机制 Redis 提供了两种主要的持久化机制&#xff1a;RDB&#xff08;Redis Database&#xff09;和 AOF&#xff08;Append Only File&#xff09;&#xff0c;下面对这两种机制进行详细介绍。 RDB&#xff08;Redis Database&#xff09; 原理&#xff1a;RDB …...

【C#】WinForm自定义控件及窗体

前言 WinForm&#xff08;Windows Forms&#xff09;是Microsoft.NET框架中的技术&#xff0c;用于开发Windows桌面应用程序。它提供了一套丰富的控件和组件。通过拖放控件、编写事件处理程序等方式快速构建用户界面。 通过属性窗口定制这些控件的外观和行为。 通过数据绑定&am…...

VideoHelper 油猴脚本,重塑你的视频观看体验

VideoHelper 油猴脚本&#xff0c;重塑你的视频观看体验 在日常上网看视频时&#xff0c;你是否也被这些问题困扰&#xff1a;视频网站开头的广告又臭又长&#xff0c;找个合适的播放倍速要在一堆选项里翻半天&#xff0c;每次手动调音量、点全屏按钮繁琐又影响沉浸感&#xf…...

从收藏夹到知识图谱:书签管理器如何重塑你的信息获取方式?

在信息爆炸的今天&#xff0c;浏览器收藏夹早已沦为 “数字垃圾堆”—— 杂乱无章的网址、重复的标签、过期的链接&#xff0c;不仅降低效率&#xff0c;更成为信息焦虑的源头。智能书签管理器通过AI分类、跨平台同步、隐私保护等黑科技&#xff0c;重塑您的数字生活方式。书签…...

SOFABoot-07-版本查看

前言 大家好&#xff0c;我是老马。 sofastack 其实出来很久了&#xff0c;第一次应该是在 2022 年左右开始关注&#xff0c;但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFABoot-00-sofaboot 概览 SOFABoot-01-蚂蚁金服开源的 s…...

[极客大挑战 2019]Http_3.19BUUCTF练习day3(1)

BUUCTF练习day3(1)_[极客大挑战 2019]Http 打开靶场&#xff0c;查看源码(如果在做题时没有什么发现就查看源码) 打开Secret.php提示没有来自https://Sycsecret.buuoj.cn 添加Referer头为https://Sycsecret.buuoj.cn&#xff08;提示说我们没有来自那个网址&#xff0c;那我们…...

golang Error的一些坑

golang Error的一些坑 golang error的设计可能是被人吐槽最多的golang设计了。 最经典的err!nil只影响代码风格设计&#xff0c;而有一些坑会导致我们的程序发生一些与我们预期不符的问题&#xff0c;开发过程中需要注意。 ​​ errors.Is​判断error是否Wrap不符合预期 ​…...

弱网测试:全链路实战、高阶策略与自动化落地

在移动互联网时代,网络环境的不确定性成为用户体验的“隐形杀手”。弱网测试不仅是质量保障的必备环节,更是提升用户留存率和业务转化率的战略手段。 本文将从 工具链深度配置、复杂场景模拟、性能优化底层逻辑 和 自动化流水线集成 四个维度,彻底解析弱网测试的完整方法论…...

Ubuntu检查并启用 Nginx 的stream模块或重新安装支持stream模块的Nginx

stream 模块允许 Nginx 处理 TCP 和 UDP 流量&#xff0c;常用于负载均衡和端口转发等场景。本文将详细介绍如何检查 Nginx 是否支持 stream 模块&#xff0c;以及在需要时如何启用该模块。 1. 检查 Nginx 是否支持 stream 模块 首先&#xff0c;需要确认当前安装的 Nginx 是…...

mac brew 安装的php@7.4 打开redis扩展

1. 找到php7.4的pecl目录 一般在这个位置 cd /usr/local/Cellar/php7.4/7.4.33_8/pecl/20190902 ls 一下 有个 redis.so 于是 直接去php.ini编辑了 php.ini的路径 vim /usr/local/etc/php/7.4/php.ini 把938行添加进去 然后重启一下 php7.4 brew services restart ph…...

Redis 内存管理

Redis 内存管理 1. Redis 给缓存数据设置过期时间的作用 给缓存数据设置过期时间&#xff08;TTL, Time-To-Live&#xff09;有以下几个重要作用&#xff1a; (1) 自动释放内存 避免缓存数据无限增长&#xff0c;导致 Redis 内存溢出。例如&#xff0c;在 会话管理、短连接…...

学习CSS滤镜属性 `filter: invert()`

一、核心机制 数学原理 invert(1) 对每个像素的RGB通道执行 颜色反相计算&#xff1a; 新通道值 255 - 原通道值 例如 rgb(255,0,0)&#xff08;纯红&#xff09;会转换为 rgb(0,255,255)&#xff08;青色&#xff09;。 透明度处理 该滤镜会保留元素的Alpha通道&#xff08;…...

网络空间安全专业发展历程及开设院校

一、专业发展历程 1. 早期探索阶段&#xff08;1990年代末—2000年代初&#xff09; &#xff08;1&#xff09;背景&#xff1a; 1990年代互联网进入中国&#xff0c;计算机病毒、黑客攻击等问题逐渐显现&#xff0c;社会对信息安全人才的需求开始萌芽。 &#xff08;2&…...

Linux中mutex机制

在Linux中&#xff0c;mutex是一种用于多线程编程的同步机制&#xff0c;用于保护共享资源&#xff0c;防止多个线程同时访问或修改这些资源&#xff0c;从而避免竞态条件的发生。mutex 是“mutual exclusion”的缩写&#xff0c;意为“互斥”。 1. Mutex 的基本概念 互斥锁&…...

Web网页

1.结构与表现分离 HTML用于结构 css用于表现&#xff0c;增加了丰富的样式效果&#xff0c;极大满足了开发者的需求 选择器&#xff1b;用于指定css样式作用的html对象{}选择某个属性 p标签 color;本颜色 font-size:子属性 字大小 font-family&#xff1b;字体 font-…...

Redis 在windows下的下载安装与配置

参考链接:https://developer.aliyun.com/article/1395346 下载 Redis 访问 Redis 下载地址&#xff1a;https://github.com/tporadowski/redis/releases 下载 Redis 时&#xff0c;你可以选择 ZIP 包或 MSI 安装&#xff1a; ZIP包&#xff1a;需要手动解压、初始化、配置和…...