自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(62)
  • 收藏
  • 关注

原创 如何验证i2c?

使用i2cdetect扫描总线是否有设备存在,断开连接线设备消失,数字代表用的是i2c第几组。#查看对应的i2c驱动是否打开。

2025-11-28 11:42:59 386

原创 I2C 多从机通信原理?

所有从机都共享两根线,通过主机发出的地址帧来判断是否该自己应答,只有匹配地址的从机会拉低 ACK。I2C 多从机通信(地址识别、冲突避免、从机如何知道轮到它)

2025-11-28 11:36:00 289

原创 i2c数据传输时序

● 一句话:I2C 的所有信息(起始、地址、读写、数据、应答、停止)都是在 SCL 高电平期间通过 SDA 线上“被谁拉低/放开”来编码的。● 一句话:起始条件之后,主机会在 8 个 SCL 周期内发出“7 位地址 + 1 位读写位”,然后等一个 ACK。● 一句话:地址成功后,后面就是一串“8 位数据 + 1 位 ACK”的重复周期,每个字节至少 9 个时钟。○ 作用:主机可以不松总线,在一次会话里先写再读(或切换从机),常用于“先写寄存器地址,再读数据”。

2025-11-28 11:35:23 337

原创 I2C 的输入/输出切换原理是什么?

I2C 线上设备不会主动输出高电平,只会在需要时把线拉低,通过硬件开漏结构实现输入输出的自动切换。I2C 的输入输出切换(主机和从机如何控制 SDA/SCL)

2025-11-28 11:34:49 375

原创 i2c的物理层原理?

一句话总结:通过一次写入寄存器地址、一次读取数据,MPU6050 按 I2C 规则返回多个字节的加速度数据。一句话总结:I2C 用两根线,通过上拉电阻保持高电平,所有设备只能拉低线路,从而实现稳定的双向通信。● MCU 发出 TMP75 的地址字节,TMP75 在 ACK 阶段拉低 SDA 表示已识别地址。● 每发送一个字节后,发送设备释放 SDA,由接收设备决定是否拉低 SDA 作为 ACK。一句话总结:不同外设通过地址区分,不会互相干扰,体现 I2C 的共享总线优势。

2025-11-28 11:34:11 381

原创 如何使用libgpiod 控制 IO?

libgpiod 是什么● libgpiod 通过 字符设备接口 访问 GPIO:○ 设备文件:/dev/gpiochip0、/dev/gpiochip1 …○ 不再用老的 /sys/class/gpio 方式。● libgpiod 提供:○ 命令行工具:gpiodetect / gpioinfo / gpioset / gpioget / gpiomon○ C 语言库:gpiod.h + libgpiod.so○ C++ / Python 封装(此处不展开)

2025-11-25 15:44:36 32

原创 如何验证gpio?

1、 查看 gpio 是否被使用和复用功能#查看已经被使用的GPIO,不会显示未使用和复用的GPIO#每个物理脚被复用成了什么功能(I2C / SD / USB / 纯 GPIO),有没有被占用(MUX UNCLAIMED) (GPIO UNCLAIMED) #分别代表没有复用功能和gpio中也没复用vcc5v0-otg-regulator gpio0:5 function usb group vcc5v0-otg-en #功能复用为电源管理节点,被当成gpio 0_5使用。

2025-11-25 15:44:02 18

原创 gpio常见模式和编号计算方式

echo 1 > /sys/class/gpio/gpio36/value # 输出高电平,约 3.3V。cat /sys/class/gpio/gpio36/value # 读取当前电平(0 或 1)echo 0 > /sys/class/gpio/gpio36/value # 输出低电平,约 0V。echo out > /sys/class/gpio/gpio36/direction # 设置为输出。2、输出模式(out)1、输入模式(in)

2025-11-25 15:43:29 16

原创 2、为什么要用“虚拟地址”访问内存

程序看到的是“虚拟门牌号”,内核负责查表找到“真实房子”;这层“幻觉”让多进程世界既安全又高效。

2025-10-31 09:11:39 291

原创 1、什么是虚拟内存地址

虚拟内存地址是程序员眼中的“门牌号”,物理内存地址才是真正的“地理位置”,CPU 的内存管理单元(MMU)负责查地图,把门牌号翻译成真实地块。

2025-10-31 09:11:04 291

原创 4、缓存污染详解与解决方案

缓存污染指的是一批短暂访问的数据占据了缓存空间,把真正的热点数据挤出内存,导致缓存命中率骤降。🧠缓存就像冰箱,原本放着常吃的菜。突然你批量塞进一堆“只用一次”的食材(例如宴会剩菜),导致平时常吃的菜被挤出来,后面要再吃还得去超市(= 磁盘 I/O)。项目缓存结构Active / Inactive 双链表Young / Old 分区 LRU晋升机制第二次访问才晋升 Active第二次访问且时间间隔 > 1s 才晋升 Young目的避免一次性访问页污染活跃缓存。

2025-10-31 09:09:52 807

原创 1、操作系统虚拟内存机制

问题场景原因解决方式malloc(8 GB) 直接失败32 位系统地址空间限制只能 3 GB64 位系统 malloc 失败overcommit = 0 拒绝超配设置为 1程序被 “Killed”OOM Killer 启动增加物理内存或启用 Swap性能变慢、磁盘“沙沙”响频繁 Swap In/Out调低 swappiness、排查大内存进程。

2025-10-31 09:08:41 341

原创 嵌入式常用通信协议对比汇总

嵌入式通信协议对比摘要: 本文系统对比了12种常见嵌入式接口协议,分为5大类:1)通用信号类(GPIO/PWM)用于基础控制;2)低速通信类(UART/I2C/SPI)适合传感器和外设;3)工业总线(CAN/FlexRay)具备抗干扰能力;4)高速多媒体接口(MIPI DSI/CSI)支持视频传输;5)存储扩展类(FlexBus/DSMC)用于外设连接。通过对比速率、同步方式、全双工特性等参数,提供了协议选型决策表,指出GPIO最简单,FlexRay可靠性最高,MIPI接口速度最快(6Gbps)。不同协议构

2025-10-25 21:34:04 475

原创 3.1、调整文件页与匿名页回收倾向

🧠swappiness 越大,系统越“爱用仓库”;swappiness 越小,系统越“勤快清理缓存”。📦 文件页 = 临时缓存,随时扔掉没关系💾 匿名页 = 程序状态,搬来搬去会卡顿把 swappiness 调小(如 10 或 0)能显著提升系统流畅度。

2025-10-24 17:13:02 269

原创 4、如何保护进程不被 OOM 杀掉

Linux系统内存不足时会触发OOM机制,通过oom_badness()函数对进程打分,选择占用内存多且分数高的进程终止。用户可通过调整/proc/[pid]/oom_score_adj参数(-1000到1000)来控制进程被杀优先级,值为-1000表示"免死金牌"。建议对系统关键服务设为-1000,普通业务进程保持默认值0,可牺牲任务设为正数。错误配置可能导致系统异常,合理使用oom_score_adj和cgroup可实现内存管理优化。

2025-10-24 17:12:19 608

原创 3、内存回收的性能影响

频繁回收内存 = 不停“搬家” → I/O 瓶颈 → 系统变慢。

2025-10-24 17:11:32 640

原创 2、哪些内存可以被回收

Linux内存回收机制主要针对文件页和匿名页两类内存。文件页来自文件缓存,可直接丢弃或写回磁盘;匿名页需通过Swap机制写入交换分区。系统基于LRU算法维护活跃和非活跃链表,优先回收不常用的内存页:干净文件页>脏文件页>匿名页。这种机制能在不终止进程的前提下高效管理内存,确保系统稳定运行。内存回收优先级体现了Linux"尽量写盘不杀进程"的设计理念。

2025-10-24 17:11:01 693

原创 1、内存分配的全过程

→ malloc() 调用 → 虚拟地址空间扩大(通过 brk/mmap,尚未映射物理页)阶段技术行为生活类比malloc()申请虚拟内存预定房间第一次访问缺页中断你到前台登记入住分配物理页前台分配房间并登记kswapd后台清理旧房清理空房间以供入住你等清洁工打扫完才能入住同步等待OOM Killer房间爆满时赶走住客强制清理占用者malloc 分配的是虚拟内存,不是物理内存;第一次访问才触发缺页中断,由内核分配物理页并建立映射;若内存紧张,内核通过。

2025-10-24 17:09:42 977

原创 3、预读机制与预读失效

预读机制(Readahead)是操作系统或数据库的一种性能优化策略:当程序读取某个文件块时,系统会预先把后续相邻的数据块也加载到内存中以减少将来可能发生的磁盘 I/O。📖例子(Linux Page Cache)磁盘最小读取单位是 4KB block;操作系统不仅读 [0,4KB),还会额外读 [4KB,8KB)、[8KB,12KB)、[12KB,16KB);这样下一次若访问 8KB 数据时,就可以直接命中缓存。📈减少磁盘 I/O 次数,提高吞吐量。

2025-10-21 21:54:25 321

原创 2、传统 LRU 算法如何管理内存数据

场景改进策略实际系统预读失效双链表(Active/Inactive)缓存污染分区 LRU(Young/Old)或 LFU综合优化结合频率与时间(ARC / LIRS)高级文件系统、数据库引擎传统 LRU:谁最近用过,谁最重要。太相信“最近”;不考虑“频率”;被“预读”和“一次性访问”轻易欺骗。🧠LRU 是缓存管理的“原型算法”,Linux 与 MySQL 都在它基础上做了“防笨优化”:——前者加“双链表”,后者加“双分区”。

2025-10-21 21:53:49 429

原创 1、Linux 与 MySQL 缓存机制

Page Cache(页缓存)内核在访问文件时,为了加速文件 I/O,把读取的文件页缓存在内存中。属于内核态内存,用来缓存磁盘上的文件数据。Buffer Pool(缓冲池)InnoDB 存储引擎在内存中维护的页级缓存,用于存储数据页、索引页、undo/redo 页等。其结构如下(图2对应):↓↓Buffer Pool(内存中的数据库页缓存)↓磁盘(数据页)Linux 的 Page Cache 是系统层通用加速器;MySQL 的 Buffer Pool 是数据库层的精细缓存。

2025-10-21 21:53:14 315

原创 2、Swap 机制与虚拟内存

定义:把一部分匿名页(堆/栈/未映射文件)临时放到磁盘/压缩内存(zram),需要再取回(Swap In)。触发两类场景内存不足→ 直接回收(同步,阻塞申请方)→ 把冷匿名页Swap Out;内存趋紧/有闲置→ kswapd 后台回收(异步)→ 先换出不常用页,减少日后卡顿。不走 Swap 的:文件页(有后备文件),优先丢弃/回写,不占 Swap 配额。🧠 类比:RAM 是办公桌,Swap 是文件柜;桌面不够,把不常翻的资料先放柜子。Swap 主要兜底匿名页,让“可用内存”看起来大于物理 RAM。

2025-10-21 21:52:26 374

原创 1、操作系统虚拟内存机制

问题场景原因解决方式malloc(8 GB) 直接失败32 位系统地址空间限制只能 3 GB64 位系统 malloc 失败overcommit = 0 拒绝超配设置为 1程序被 “Killed”OOM Killer 启动增加物理内存或启用 Swap性能变慢、磁盘“沙沙”响频繁 Swap In/Out调低 swappiness、排查大内存进程。

2025-10-21 21:51:34 270

原创 损失函数 · 梯度下降 · 反向传播--过程

所以,损失函数不是拍脑袋选的,而是理论上代表“预测与真相差距”的可微指标。● 如果脚下坡度朝上(梯度为正),说明你走的方向会“上山”,损失变大;● 如果脚下坡度朝下(梯度为负),说明你走的方向能“下山”,损失变小;● 坡越陡(梯度绝对值越大),说明“这条路能让误差变化得更快”。“损失”不是凭空规定的,它是“我们衡量预测正确与否的标尺”。损失值是模型表现的“温度计”:高 = 错多,低 = 预测准。这个函数的值,就是我们训练中要最小化的 损失(Loss)。计算损失(Loss) —— 衡量模型预测与目标的差距。

2025-10-19 21:00:25 440

原创 梯度下降与反向传播(Gradient Descent & Backpropagation)

● 梯度下降(Gradient Descent) 是一种参数优化算法,通过沿着损失函数下降最快的方向调整参数,逐步逼近最优解。● 反向传播(Backpropagation, BP) 是一种梯度计算方法,用于高效求出神经网络中每个参数对损失的偏导。无论是 CNN、RNN、Transformer,核心优化循环都离不开 BP + GD。● 想象你在夜晚的山谷中,手中只有一个坡度传感器(梯度)。● 每次你感知脚下的坡度,就沿最陡的下坡方向迈出一小步。● 走几步,坡度变平——说明接近谷底(梯度趋近 0)。

2025-10-19 20:59:29 613

原创 Transform基础详解

● Transform 在 Transformer 里指 特征空间的变换:让每个输入向量先“看见全局”,再重写自己的表示。“杯子”token 关注“把手/边缘/高光”token,学习整体—部件关系。○ 装配识别:零件 A 的 token 关注孔/边/法线 token,学习“配合—约束”。● 多头分工:不同头侧重不同关系(语法、局部纹理、长程依赖),过多头可能冗余。● 目标:更好地建模全局依赖与长程关系(语言、视觉、多模态均适用)。○ 代词指代消解、长依赖语义重建(“它”更关注“苹果”而非“她”)。

2025-10-19 20:58:55 657

原创 CNN-卷积神经网络详解

● CNN(Convolutional Neural Network) 是一种利用局部感受野与参数共享思想的神经网络,用于高效提取空间特征。● 目标:从像素层逐级抽象出语义层特征,用于识别、检测或理解视觉信息。(卷积 → 激活 → 池化 → 平铺 → 全连接 → Softmax)这样网络能自动学习出图像中的局部模式(如边缘、角点、纹理)。● 目标检测:Faster R-CNN、YOLO、SSD。从“像素点” → “局部结构” → “整体语义”。多层卷积叠加 → 从“线条”逐渐识别成“物体”。

2025-10-18 20:36:16 394

原创 七、线程崩溃了,进程也会崩溃吗?

自定义处理函数(打印后退出)\n", sig);exit(sig);// 自己选择退出// 非法地址*p = 10;// 触发 SIGSEGV → 进入 sigHandler忽略信号(⚠️非所有信号可忽略,如 SIGKILL=9 不可)// 尝试忽略段错误(不推荐)printf("仍然运行到这里\n");生产中常见的“优雅停机”:向服务发,进程自定义处理(释放资源、停止接入、保存状态),最后自行退出。不要用kill -9SIGKILL),它无法被捕获/忽略,会立刻终止导致资源来不及清理。

2025-10-18 20:31:56 763

原创 六、一个进程最多可以创建多少个线程

系统类型栈空间大小理论线程上限实测线程上限主要限制32 位10 MB≈ 300≈ 300虚拟空间3 GB32 位512 KB≈ 6000≈ 6000虚拟空间3 GB64 位8 MB≈ 千万级≈ 1455364 位512 KB理论百万级≈ 5 万CPU瓶颈、max_map_count64 位100 MB理论百万级≈ 2.6 万虚拟空间映射上限用户空间仅 3 GB,理论上一个进程最多约几百线程。虚拟空间极大,限制来自系统参数与物理资源。

2025-10-18 20:30:30 513

原创 3、乐观锁与悲观锁

项目悲观锁乐观锁优点逻辑简单、安全、无需冲突检测高并发性能好、无内核切换缺点上下文切换开销大、阻塞明显实现复杂、可能频繁重试适用场景高冲突、高安全需求冲突少、性能敏感业务典型应用数据库事务锁、文件写入锁在线文档、Git、缓存更新“我先锁上,谁也别动。”(预防为主)“我先干了,不行再说。”(事后验证)一句话总结:悲观锁牺牲并发来换安全,乐观锁牺牲重试来换性能。

2025-10-18 20:29:48 597

原创 2、读写锁(Read-Write Lock)

特性读写锁优点读写锁缺点并发性多读线程并发访问写锁期间全部阻塞性能读多写少时性能优越写多时性能不如互斥锁公平性可实现公平机制防止饥饿需要额外队列维护实现复杂度较高调试难度更大读写锁核心思想:读共享、写独占。应用场景:读多写少。三种调度模式读优先:性能高但可能饿写;写优先:公平写但可能饿读;公平锁:性能略降但无饥饿。底层实现:可基于互斥锁或自旋锁;选择建议写频繁:用互斥锁;读远多于写:用读写锁;用户态轻量并发:可用自旋型 RWLock。

2025-10-18 20:29:10 531

原创 1、互斥锁与自旋锁

特点互斥锁自旋锁优点节省CPU、不忙等、系统支持快速响应、无上下文切换缺点上下文切换慢、进入内核态消耗CPU、锁时间长会浪费性能使用建议临界区执行时间长临界区执行时间短互斥锁靠“睡眠等锁”,自旋锁靠“死盯锁”。如果锁持有时间短,就盯着等(自旋锁);如果锁持有时间长,就先去睡(互斥锁)。

2025-10-17 17:06:30 649

原创 4、避免死锁问题的发生

锁等级(Lock Rank)

2025-10-17 17:05:12 710

原创 3、死锁问题的定位与排查(pstack + gdb )

项目线程A线程B已持有锁mutex_Amutex_B等待锁mutex_Bmutex_A状态等待等待结论A 等 B,B 等 A死锁成立工具作用使用命令特点pstack打印线程调用栈快速发现线程停在哪个函数gdb附加调试进程可查看具体锁对象的拥有者strace追踪系统调用可看到线程卡在futex()等锁等待系统调用看现象:程序不退出,CPU 占用低;看栈pstack多次输出不变,卡在;查线程确定线程号;查锁归属p mutex_Ap mutex_B找出持有者;验证环路。

2025-10-17 17:04:40 923

原创 2、模拟死锁问题的产生

死锁本质:“你等我,我等你,谁也不放手。统一加锁顺序(破坏环路等待);一次性获取全部资源或定时重试(破坏持有并等待);尽量缩小锁粒度与持有时间。申请有序,用完即放;不拿半套,不做死等。

2025-10-17 17:04:01 497

原创 1、死锁的概念

在多线程或多进程系统中,如果多个线程因为争夺资源而相互等待,导致所有线程都无法继续执行,就发生了“死锁”。换句话说:死锁是一种“大家都等别人先动,但谁也动不了”的僵局。死锁是“资源相互等待”的僵局。同时满足四个条件:互斥、持有并等待、不可剥夺、环路等待。想避免,就打破其中之一。或者更形象地记:“谁都不肯放手,谁都等别人放手 —— 就死锁了。

2025-10-17 17:03:30 247

原创 4、malloc 内存分配器是怎样实现的

申请时从堆或映射区切块;释放时根据块头自动识别大小并复用;混合使用 brk 与 mmap平衡性能与碎片;让整个系统既快又高效。free(ptr)之所以能“知道”要释放多少内存,是因为 malloc 在分配时就在返回指针前,藏了一份描述该块大小的账单(Header)。

2025-10-16 09:08:36 836

原创 3、为什么 malloc 不全用 mmap(也不全用 brk)

malloc采用brk和mmap混合分配策略是出于性能与碎片管理的平衡考虑。brk适合小内存分配,速度快但容易产生碎片;mmap适合大内存分配,释放干净但系统调用开销大。全用mmap会导致小内存分配性能低下,全用brk则会造成内存碎片问题。混合策略结合两者优势:小内存用brk减少系统调用,大内存用mmap避免碎片。这种"看情况下菜"的方式实现了内存分配的高效与合理。

2025-10-16 09:06:56 402

原创 2、malloc 是如何分配内存的

malloc 不是系统调用,而是一个用户态分配器。它通过brk()和mmap()两种机制向内核申请虚拟地址空间真正的物理内存在首次访问时才分配。小块留在堆内复用,大块直接映射并在释放时归还操作系统。

2025-10-16 09:05:49 395

原创 1、Linux 进程的内存分布

用户空间负责程序逻辑与数据存储;内核空间负责资源与安全管理;堆与栈是动态内存的核心区;malloc / mmap 分别管理不同规模的分配需求。从用户视角看:程序有完整的 4GB 或 128TB 地址空间;从内核视角看:只是不同虚拟页映射到物理内存的“假象”,一切由内核统一调度。

2025-10-15 22:09:30 872

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除