Ubuntu 下 nginx-1.24.0 源码分析 - ngx_atomic_cmp_set 函数
目录
修正
执行
./configure
命令时,输出:
checking for OS
+ Linux 6.8.0-52-generic x86_64
checking for C compiler ... found
+ using GNU C compiler
+ gcc version: 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
所以当前环境是 x86_64
于是在 src\os\unix\ngx_atomic.h 中
#include "ngx_gcc_atomic_x86.h"
被包含
src/os/unix/ngx_gcc_atomic_x86.h 中:
static ngx_inline ngx_atomic_uint_t ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,ngx_atomic_uint_t set) {u_char res;__asm__ volatile (NGX_SMP_LOCK" cmpxchgl %3, %1; "" sete %0; ": "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");return res; }
函数功能:
原子地比较
*lock
的值是否等于old
:若相等:将
*lock
设置为set
,并返回1
(成功)若不相等:不修改
*lock
,返回0
(失败)
内联汇编实现
NGX_SMP_LOCK
宏定义,在多核(SMP)系统中扩展为
lock
前缀,确保指令的原子性;单核系统中可能为空
cmpxchgl %3, %1
x86 的原子比较并交换指令:
- 比较
%1
(即*lock
)与eax
寄存器(隐含使用,值为old
)- 若相等,将
%3
(即set
)写入*lock
;否则,将*lock
的值加载到eax
sete %0
根据
cmpxchgl
结果(ZF 标志位)设置res
为0
或1
输入输出约束
输出
"=a" (res)
:结果res
通过eax
寄存器返回输入
"m" (*lock), "a" (old), "r" (set)
:
*lock
作为内存操作数
old
存入eax
(隐含用于cmpxchgl
的比较)
set
存入通用寄存器
"cc", "memory"
:告知编译器条件寄存器和内存可能被修改
内联汇编语法
操作数占位符
%0, %1, %2, %3
:按操作数出现顺序编号:
%0
→"=a" (res)
(输出)%1
→"m" (*lock)
(输入)%2
→"a" (old)
(输入)%3
→"r" (set)
(输入)操作数约束(Constraints)
输出操作数
"=a" (res)
=
:表示只写(输出)。a
:使用eax
寄存器。res
:C变量,接收结果(0或1)
"m" (*lock)
m
:内存操作数,直接操作*lock
的内存地址
"a" (old)
a
:将old
的值存入eax
寄存器(cmpxchgl
隐式使用eax
进行比较)。
"r" (set)
r
:将set
的值存入任意通用寄存器(如ebx
、ecx
等)。Clobber列表
"cc"
:表示指令修改了标志寄存器(如 ZF、CF)。"memory"
:表示指令可能修改内存,强制编译器刷新内存缓存。cmpxchgl 源操作数, 目标操作数
比较
目标操作数
(即*lock
)与eax
的值(old
)。若相等:
将
源操作数
(即set
)写入目标操作数
(*lock
)。设置 ZF(Zero Flag)为 1。
若不相等:
将
目标操作数
(*lock
)的值加载到eax
。设置 ZF 为 0。
sete %0
sete
:若 ZF=1(即比较成功),将目标(%0
,即res
)设为 1,否则设为 0。- 由于
%0
约束为"=a"
,结果通过eax
写入res
。
执行流程
将
old
加载到eax
。原子比较
*lock
与eax
:相等 → 将
set
写入*lock
,ZF=1。不等 → 将
*lock
值加载到eax
,ZF=0。根据 ZF 设置
res
(1 或 0)。返回
res
。
意图
实现原子操作
通过cmpxchgl
指令和lock
前缀,确保在多核环境下的原子性,避免竞态条件。跨平台兼容性
使用
NGX_SMP_LOCK
宏适配不同平台(如单核无需lock
前缀)
NGX_SMP_LOCK
在 src\os\unix\ngx_gcc_atomic_x86.h
#if (NGX_SMP) #define NGX_SMP_LOCK "lock;" #else #define NGX_SMP_LOCK #endif
objs/ngx_auto_config.h 中
#ifndef NGX_SMP #define NGX_SMP 1 #endif
所以
NGX_SMP_LOCK 是 "lock;"
- 无
lock
:cmpxchgl
本身是原子的,但仅限单核环境。- 有
lock
:确保多核环境下的原子性,完整执行“比较-交换”操作。
修正
以上部分 可能是错误的
在 src\os\unix\ngx_atomic.h 中:
#define ngx_trylock(lock) (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1))
这样定义了 ngx_trylock
但对于 ngx_atomic_cmp_set 的定义可能判断错了
在 我的Ubuntu 环境中
objs/ngx_auto_config.h:9:#define NGX_HAVE_GCC_ATOMIC 1
也就是在 objs/ngx_auto_config.h 中
定义了
#ifndef NGX_HAVE_GCC_ATOMIC #define NGX_HAVE_GCC_ATOMIC 1 #endif
在 ngx_atomic.h 中
#if (NGX_HAVE_LIBATOMIC) 省略 #elif (NGX_HAVE_GCC_ATOMIC) 省略 #define ngx_atomic_cmp_set(lock, old, set) \__sync_bool_compare_and_swap(lock, old, set)
#elif (NGX_HAVE_GCC_ATOMIC) 条件成立
所以 ngx_atomic_cmp_set 的定义应该是:
#define ngx_atomic_cmp_set(lock, old, set) \__sync_bool_compare_and_swap(lock, old, set)
在Ubuntu的x86_64架构下,
NGX_HAVE_GCC_ATOMIC
会被定义ngx_atomic_cmp_set 在支持GCC原子内置函数的情况下,这个函数应该会被定义为上述情况
__sync_bool_compare_and_swap
是 GCC 提供的一个内置原子操作函数,用于实现多线程环境下的无锁同步。其作用是在原子操作中比较并交换(Compare-and-Swap, CAS)一个值,常用于实现线程安全的操作。
函数原型
bool __sync_bool_compare_and_swap(type *ptr, type oldval, type newval);
- 参数:
ptr
:指向需要操作的内存地址的指针。oldval
:期望的旧值。newval
:要设置的新值。- 返回值:
- 如果
*ptr
的当前值等于oldval
,则将*ptr
设置为newval
,并返回true
。- 否则不修改内存,返回
false
。底层原理
该函数依赖硬件级别的原子指令(如 x86 的
CMPXCHG
指令)实现,确保多线程环境下操作的原子性函数由 GCC 编译器直接提供,无需像标准库函数(如
printf
)那样通过#include
引入头文件。直接在代码中调用即可
gcc -E
鉴于有时预编译指令较多且嵌套,难以判断具体使用的哪一个定义
于是改用
gcc -E 的方法
- 作用:运行 GCC 的 预处理阶段,处理以下内容:
- 展开
#include
引入的头文件。- 替换
#define
定义的宏。- 处理
#ifdef
/#if
等条件编译指令。- 删除注释。
- 输出:预处理后的纯 C 代码(未编译)。
gcc -E src/core/ngx_times.c \-I src/core \-I src/event \-I src/event/modules \-I src/os/unix \-I objs \> ngx_times_preprocessed.c
-I 添加头文件搜索路径
> ngx_times_preprocessed.c
- 作用:将预处理结果重定向到文件
ngx_times_preprocessed.c
- 文件内容:展开后的完整代码
找到原本 ngx_times.c中
void ngx_time_update(void) {u_char *p0, *p1, *p2, *p3, *p4;ngx_tm_t tm, gmt;time_t sec;ngx_uint_t msec;ngx_time_t *tp;struct timeval tv;if (!ngx_trylock(&ngx_time_lock)) {return;}
ngx_time_update 函数中,struct timeval tv; 后,ngx_trylock 调用的地方
在
ngx_times_preprocessed.c 中的位置
if (!(*(&ngx_time_lock) == 0 && __sync_bool_compare_and_swap(&ngx_time_lock, 0, 1))) {return;}
这里是展开后的样子
所以 确认是 调用了
__sync_bool_compare_and_swap
相关文章:
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_atomic_cmp_set 函数
目录 修正 执行 ./configure 命令时,输出: checking for OS Linux 6.8.0-52-generic x86_64 checking for C compiler ... found using GNU C compiler gcc version: 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) 所以当前环境是 x86_64 于是在 src…...
为什么我用Python控制仪器比C#慢很多?如何优化性能?
在自动化测试、实验室仪器控制等领域,Python、C# 和 C 是常见的编程语言选择。最近,我在使用 Python 控制仪器时,发现其交互速度明显比 C# 慢很多。这让我感到困惑,毕竟 Python 以其简洁和高效著称,为什么会出现这种情…...
Linux虚拟机克隆
克隆 从现有虚拟机(关机状态)克隆出新虚拟机,右键选择管理>克隆: 选择完整克隆 设置虚拟机名称及存储位置 开机修改系统相关配置 注意: 使用root 用户。 修改vim /etc/sysconfig/network-scripts/ifcfg-ens33 ,修改IP 地址 vim /etc/sysconfig…...
开发完的小程序如何分包
好几次了,终于想起来写个笔记记一下 我最开始并不会给小程序分包,然后我就各种搜,发现讲的基本上都是开发之前的小程序分包,可是我都开发完要发布了,提示我说主包太大需要分包,所以我就不会了。。。 好了…...
气体控制器联动风机,检测到环境出现异常时自动打开风机进行排风;
一、功能:检测到环境出现异常时自动打开风机进行排风; 二、设备: 1.气体控制器主机:温湿度,TVOC等探头的主机,可上报数据,探头监测到异常时,主机会监测到异常可联动风机或声光报警…...
攻防世界33 catcat-new【文件包含/flask_session伪造】
题目: 点击一只猫猫: 看这个url像是文件包含漏洞,试试 dirsearch扫出来/admin,访问也没成功(--delay 0.1 -t 5) 会的那几招全用不了了哈哈,那就继续看答案 先总结几个知识点 1./etc/passwd&am…...
让文物“活”起来,以3D数字化技术传承文物历史文化!
文物,作为不可再生的宝贵资源,其任何毁损都是无法逆转的损失。然而,当前文物保护与修复领域仍大量依赖传统技术,同时,文物管理机构和专业团队的力量相对薄弱,亟需引入数字化管理手段以应对挑战。 积木易搭…...
Java+vue前后端分离项目集群部署
一、项目概述 假设我们有一个前后端分离的项目,前端使用React或Vue框架,后端使用Spring Boot或Node.js。我们将分别部署前端和后端到集群环境中。 二、准备工作 1. 代码准备:确保前端和后端代码已经开发完成,并通过本地测试。 2…...
【算法解析】(2)分治算法:归并排序和快速排序
1. 分治算法(Divide and Conquer) 分治算法的核心思想是将一个大问题分解为多个小问题,分别解决这些小问题,然后将小问题的解合并起来得到大问题的解。 2. 算法步骤 分治算法通常包含以下三个步骤: 分解(Divide):将原问题分解为若干个规模较小、相互独立、与原问题…...
Qt文本处理【正则表达式】示例详解:【QRegularExpression】
在 Qt 中,正则表达式是处理文本的强大工具,它能够帮助我们匹配、搜索和替换特定的字符串模式。自 Qt 5 起,QRegularExpression 类提供了对 ECMAScript 标准的正则表达式支持,这使得它在处理各种复杂的字符串任务时变得更加高效和灵…...
在 Navicat 17 中扩展 PostgreSQL 数据类型 - 枚举类型
枚举类型 在 Navicat Premium 17 中创建 PostgreSQL 的自定义数据类型的系列中,我们已经探索了多个主题。在 第 1 部分 ,我们学习了如何为 免费 DVD 租赁数据库 创建自定义域。上周,我们创建了一个复合类型,用于从用户定义的函数…...
Spring Boot + MyBatis Field ‘xxx‘ doesn‘t have a default value 问题排查与解决
目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 执行代码的时候,出现某个字段无法添加 ### Error updating database. Cause: java.sql.SQLException: Field e_f_id doesnt have a default value ### The error may exist in cn...
python基础入门:6.2JSON与CSV数据处理
Python数据处理实战:JSON与CSV高效转换指南 # 天气数据转换示例 import json import csv from datetime import datetimedef process_weather_data(json_file, csv_file):"""将天气JSON数据转换为CSV格式"""with open(json_file, r,…...
尚硅谷课程【笔记】——大数据之Zookeeper【二】
课程视频:【尚硅谷Zookeeper教程】 四、Zookeeper实战 4.1分布式安装部署 1. 集群规划 在Hadoop102、Hadoop103和Hadoop104三个节点上部署Zookeeper 2. 解压安装 1)解压Zookeeper.tar.gz到指定目录 tar -zxvf zookeeper-3.7.2.tar.gz -C /opt/mod…...
机器学习常用包matplotlib篇(一)简单图像绘制
前言 Matplotlib 是支持 Python 语言的开源绘图库,简单且完善。 一、环境配置 1.环境设置 在 Notebook 环境绘图时,需先运行 %matplotlib inline 命令,将绘制图形嵌入当前页面。在桌面环境绘图,无需上述命令,而是在…...
JUnit断言方法详解与实战
在Java开发中,JUnit是一个不可或缺的单元测试框架,而org.junit.Assert类中的断言方法则是JUnit的核心功能之一。通过这些方法,我们可以方便地验证代码的正确性。本文将详细介绍一些常用的断言方法,并通过实例展示它们的使用。 一、…...
npm运行Vue项目报错 error:0308010c:digital envelope routines::unsupported
大家好,我是 程序员码递夫。 问题 VSCode 运行Vue项目,提示错误: building 2/2 modules 0 activeError: error:0308010c:digital envelope routines::unsupported 解决方法 原因是 npm 高版本(大于17),对ssl的处理做了改进&…...
C语言操作符详解
引言 C语言作为一种强大而灵活的编程语言,操作符是其重要组成部分。操作符用于执行各种运算,如算术运算、逻辑运算、比较运算等。深入理解C语言操作符,能帮助开发者编写出高效、准确的代码。 算术操作符 基本算术操作符 - (加法…...
Lucene 中的并发错误:如何修复乐观并发失败
作者:来着 Elastic Benjamin Trent 及 Ao Li 感谢 CMU PASTA 实验室开发的确定性并发测试框架 Fray,我们找到了一个棘手的 Lucene 漏洞并将其修复。 是的,另一个修复错误博客。但这个故事有一个转折,一位开源英雄突然出现并拯救了…...
Oracle的学习心得和知识总结(三十三)|Oracle数据库数据库的SQL ID的底层计算原理分析
目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《Oracle Database SQL Language Reference》 2、参考书籍:《PostgreSQL中文手册》 3、EDB Postgres Advanced Server User Gui…...
C# OpenCV机器视觉:智能水果采摘
在一个风景如画的小镇边上,有一座阿强家祖传的果园。每到水果成熟的季节,果园里硕果累累,红彤彤的苹果、黄澄澄的梨子、紫莹莹的葡萄,散发着诱人的香气。然而,这丰收的喜悦却总被一件烦心事笼罩 —— 摘水果。 “哎呀…...
逻辑回归不能解决非线性问题,而svm可以解决
逻辑回归和支持向量机(SVM)是两种常用的分类算法,它们在处理数据时有一些不同的特点,特别是在面对非线性问题时。 1. 逻辑回归 逻辑回归本质上是一个线性分类模型。它的目的是寻找一个最适合数据的直线(或超平面&…...
celery + redis - 入门
文章目录 一、基本使用编写任务启动服务创建生产者获取状态和结果二、多目录结构异步执行编写服务启动服务调用服务获取结果https://www.bilibili.com/video/BV1jg4y13718 https://www.cnblogs.com/pyedu/p/12461819.html 一、基本使用 编写任务 celery_task.py import cel…...
SAP-ABAP:在LOOP循环中 ASSIGNING FIELD-SYMBOL的使用代码详解
在ABAP中,ASSIGNING FIELD-SYMBOL的作用是直接引用内表行的数据,避免不必要的数据复制,从而提升性能和代码效率。以下是其核心作用和优势: 基本语法 LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs>)." 处理逻辑 ENDLOOP.i…...
SpringBoot启动流程简略版
启动入口 (main 方法) ↓ SpringApplication 初始化 ↓ 加载配置 (application.properties/yml) ↓ 创建 ApplicationContext ↓ 刷新 ApplicationContext ↓ - 加载 Bean 定义 - 执行自动配置 - 实例化 Bean - 依赖注入 - 调用初…...
Python:凯撒密码
题目内容: 凯撒密码是古罗马恺撒大帝用来对军事情报进行加密的算法,它采用了替换方法对信息中的每一个英文字符循环替换为字母表序列该字符后面第三个字符,对应关系如下: 原文:A B C D E F G H I J K L M N O P Q R …...
element-plus 解决el-dialog背后的页面滚动问题,及其内容有下拉框出现错位问题
这个问题通常是因为 el‑dialog 默认会锁定 body 的滚动(通过给 body 添加隐藏滚动条的样式),从而导致页面在打开对话框时跳转到顶部。解决方法是在使用 el‑dialog 时禁用锁定滚动功能。 <el-dialogv-model"dialogVisible":lo…...
Android和DLT日志系统
1 Linux Android日志系统 1.1 内核logger机制 drivers/staging/android/logger.c static size_t logger_offset( struct logger_log *log, size_t n) { return n & (log->size - 1); } 写的off存在logger_log中(即内核内存buffer)&am…...
Ubuntu 安装 NVIDIA 驱动实操指南(含卸载)
本文将详细介绍如何在Ubuntu上安装和配置NVIDIA显卡驱动。以下是一步步的操作流程,包括禁用开源驱动的步骤。 步骤 1:安装依赖 首先,确保系统中已安装gcc和make,这些是编译驱动所需的依赖。 sudo apt update sudo apt install …...
在postman中设置环境变量和全局变量以及五大常用响应体断言
一、什么是环境变量和全局变量 环境变量(Environment Variables)和全局变量(Global Variables)是 Postman 中用于存储和管理数据的两种变量类型,它们可以提高 API 测试的灵活性和可维护性。 1、 环境变量(…...
32单片机学习记录1之GPIO
32单片机学习记录1之GPIO 前置 GPIO口在单片机中扮演着什么角色? 在单片机中,GPIO口(General Purpose Input/Output) 是一种通用输入/输出接口,扮演着连接单片机与外部设备的桥梁角色。具体来说,它在单片…...
负载测试和压力测试的原理分别是什么
负载测试和压力测试是性能测试的两种主要类型,它们的原理和应用场景有所不同。 负载测试(Load Testing) 原理: 负载测试通过模拟实际用户行为,逐步增加系统负载,观察系统在不同负载下的表现。目的是评估系…...
openAI官方prompt技巧(二)
1. 赋予 ChatGPT 角色 为 ChatGPT 指定一个角色,让其从特定的身份或视角回答问题。这有助于生成针对特定受众或场景的定制化回答。 例如: 你是一名数据分析师,负责我们的市场营销团队。请总结上个季度的营销活动表现,并强调与未…...
javaEE-11.javaScript入门
目录 一.什么是javaScript 二.快速实现 三.JS引入方式 1.行内引入: 2.内部引入: 3.外部引入: 四.基础语法 1.变量 变量命名规则: 2.数据类型 3.运算符 五.JS对象 1.数组 创建数组: 2.操作数组 3.函数 函数注意事项: 函数参数: 4.对象 1.使用字面量 创建对象:…...
Word成功接入DeepSeek详细步骤
原理 原理是利用Word的VBA宏,写代码接入API。无需下载额外插件。 步骤一、注册硅基流动 硅基流动统一登录 注册这个是为了有一个api调用的api_key,有一些免费的额度可以使用。大概就是这个公司提供token,我们使用这个公司的模型调用deepsee…...
单片机简介
一、单片机简介 电脑和单片机性能对比 二、单片机发展历程 三、CISC VS RISC...
GitCode 助力 Dora SSR:开启游戏开发新征程
项目仓库(点击阅读原文链接可直达) https://gitcode.com/ippclub/Dora-SSR 跨越技术藩篱,构建游戏开发乐园 Dora SSR 是一款致力于打破游戏开发技术壁垒的开源游戏引擎。其诞生源于开发者对简化跨平台游戏开发环境搭建的强烈渴望࿰…...
[python SQLAlchemy数据库操作入门]-25.股票数据可视化:将 SQLAlchemy 数据呈现给用户
哈喽,大家好,我是木头左! 本文将探讨如何利用SQLAlchemy从数据库中提取股票数据,并使用现代数据可视化工具将这些数据以直观的方式呈现给用户。将通过一系列步骤来演示这个过程,包括设置环境、连接数据库、提取数据、处理数据以及最终的可视化展示。 安装必要的库 接下来…...
android的Lifecycle简介
嗯,我现在需要了解Android的Lifecycle组件。Lifecycle是Jetpack的一部分,对吧?听说它帮助管理Activity和Fragment的生命周期,避免内存泄漏。那它具体是怎么工作的呢? 首先,LifecycleOwner和LifecycleObser…...
SQL-leetcode—1327. 列出指定时间段内所有的下单产品
1327. 列出指定时间段内所有的下单产品 表: Products ------------------------- | Column Name | Type | ------------------------- | product_id | int | | product_name | varchar | | product_category | varchar | ------------------------- product_id 是该表主键(具…...
在Uniapp中使用阿里云OSS插件实现文件上传
在开发小程序时,文件上传是一个常见的需求。阿里云OSS(Object Storage Service)是一个强大的云存储服务,可以帮助我们高效地存储和管理文件。本文将介绍如何在Uniapp小程序中使用阿里云OSS插件实现文件上传功能。 1. 准备工作 首…...
C#中的序列化和反序列化
序列化是指将对象转换为可存储或传输的格式,例如将对象转换为JSON字符串或字节流。反序列化则是将存储或传输的数据转换回对象的过程。这两个过程在数据持久化、数据交换以及与外部系统的通信中非常常见 把对象转换成josn字符串格式 这个过程就是序列化 josn字符…...
IGBT的两级关断
IGBT(绝缘栅双极型晶体管)的两级关断(Two-stage turn-off)是一种优化关断过程的方法,主要用于减少关断时的电压过冲和dv/dt(电压变化率)过高的问题,特别是在大功率应用中(…...
TCP/IP 协议图解 | TCP 协议详解 | IP 协议详解
注:本文为 “TCP/IP 协议” 相关文章合辑。 未整理去重。 TCP/IP 协议图解 退休的汤姆 于 2021-07-01 16:14:25 发布 TCP/IP 协议简介 TCP/IP 协议包含了一系列的协议,也叫 TCP/IP 协议族(TCP/IP Protocol Suite,或 TCP/IP Pr…...
PyCharm结合DeepSeek-R1
PyCharm结合DeepSeek-R1,打造专属 AI 编程助手 在程序员的日常工作中,提高编程效率、快速解决代码问题是重中之重。今天给大家分享一个强强联合的组合 ——PyCharm 插件 Continue 与 DeepSeek-R1,它们能帮你打造出强大的个人 AI 编程助手。 …...
深入理解Java对接DeepSeek
其实,整个对接过程很简单,就四步,获取key,找到接口文档,接口测试,代码对接。 1.获取 KEY https://platform.deepseek.com/transactions 直接付款就是了(现在官网暂停充值2025年2月7日…...
【RabbitMQ的x-death头】消息死亡记录头流转示例
Header(name "x-death", required false) List<Map<String,Object>> xDeath 是用于捕获RabbitMQ自动生成的 消息死亡记录头信息。以下是详细解析和实际应用示例: x-death头的作用 死亡原因追踪:记录消息被拒绝/过期的完整生命周…...
【DeepSeek】在本地计算机上部署DeepSeek-R1大模型实战(完整版)
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈人工智能与大模型应用 ⌋ ⌋ ⌋ 人工智能(AI)通过算法模拟人类智能,利用机器学习、深度学习等技术驱动医疗、金融等领域的智能化。大模型是千亿参数的深度神经网络(如ChatGPT&…...
二、通义灵码插件保姆级教学-IDEA(使用篇)
一、IntelliJ IDEA 中使用指南 1.1、代码解释 选择需要解释的代码 —> 右键 —> 通义灵码 —> 解释代码 解释代码很详细,感觉很强大有木有,关键还会生成流程图,对程序员理解业务非常有帮忙,基本能做到哪里不懂点哪里。…...
北斗导航 | 基于多假设解分离(MHSS)模型的双星故障监测算法(MATLAB代码实现——ARAIM)
===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 双星故障监测算法 一、多星故障MHSS模型流程1、数据预处理2、构建假设模…...