自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

  • 博客(47)
  • 资源 (7)
  • 收藏
  • 关注

原创 Linux内核伙伴系统(Buddy System)原理详解

Linux内核伙伴系统(Buddy System)是一种高效的物理内存管理算法,通过将内存按2的幂次组织实现连续内存分配。其核心机制包括: 内存按order(阶)划分,从4KB(2^0)到4MB(2^10)不等 使用zone和free_area数据结构管理空闲块链表 分配时优先匹配合适大小的块,否则分割大块 释放时自动检查并合并伙伴块(大小相同、物理相邻的空闲块) 通过struct page描述符和lru链表实现块管理 该系统平衡了内存分配效率与碎片问题,是Linux内核物理内存管理的核心机制。

2025-12-11 21:42:27 952

原创 Linux侵入式链表详解

链表节点直接嵌入到数据结构内部,而不是通过指针指向独立的数据节点。在侵入式链表中,链表节点(list_head)是数据结构的一个成员,而不是独立存在的。这种设计使得链表操作更加高效,并且不需要额外的内存分配。特性传统链表自包含链表侵入式链表数据存储外部对象(通过指针)节点内部数据结构内部灵活性高(可存储任意类型)低(固定类型)高(任意类型)内存开销中等(需要指针)低最低适用场景通用场景简单固定类型系统编程、高性能场景/**

2025-12-11 21:32:42 1227

原创 Linux内核自旋锁实现详解

本文详细介绍了Linux内核中自旋锁的实现原理与工作机制。自旋锁是一种通过忙等待实现同步的锁机制,适用于临界区执行时间短的场景。文章分析了自旋锁与互斥锁的关键区别,并重点阐述了ARM64架构下采用的Ticket自旋锁实现,包括其数据结构、原子操作原理以及获取/释放锁的流程。Ticket锁通过next和owner两个票据号实现公平排队机制,避免了传统自旋锁的饥饿问题。文中还通过代码注释详细解析了ARM64架构下自旋锁的汇编实现细节,包括LL/SC和LSE两种不同的原子操作实现路径。

2025-12-06 10:21:52 982

原创 ARM架构中的Release语义详解

本文摘要: ARM架构采用弱内存顺序模型,允许指令重排序但需要显式同步。Release语义是一种单向内存屏障,确保之前的写操作在Release完成前对其他CPU可见。ARM64提供专门的Release存储指令(如stlrb/stlr),Linux内核通过__smp_store_release宏实现。Release语义保证:1) 之前写操作对其他CPU可见;2) 限制指令重排序;3) 与Acquire操作配对形成同步关系,确保多核间数据可见性。LSE扩展还提供带Release语义的原子操作指令(如staddl

2025-11-30 10:16:49 680

原创 Platform子系统内核实现详解

Linux Platform子系统是内核中管理非标准总线设备的伪总线框架,主要用于SoC平台上的外设控制器。该系统采用三层架构设计:设备模型抽象层(集成设备管理框架)、Platform核心层(提供总线类型、设备/驱动结构及匹配机制)和驱动实现层。核心数据结构包括platform_device(描述设备资源)、platform_driver(实现驱动功能)和platform_device_id(支持ID表匹配)。该系统通过统一设备模型、资源抽象、设备树支持等机制,将非标准总线设备纳入Linux设备管理框架,并

2025-11-23 09:15:59 687

原创 Linux I2C子系统

Linux I2C子系统采用三层架构:用户空间通过/dev/i2c-X访问;核心层(i2c-core)管理设备模型和总线,提供统一API;驱动层分为适配器驱动(i2c-adapter)实现硬件操作和设备驱动(i2c-driver)实现设备功能。关键数据结构包括i2c_adapter(控制器抽象)、i2c_client(设备表示)、i2c_driver和设备消息i2c_msg。适配器驱动通过实现master_xfer等核心函数完成底层通信,为上层提供统一接口。

2025-11-20 19:54:23 610

原创 linux0.12 fork 系统调用源码阅读

本文分析了Linux 0.12中fork系统调用的实现过程。fork通过int $0x80触发系统调用,内核入口函数_system_call保存寄存器并调用sys_fork。sys_fork先通过find_empty_process查找空闲任务槽,再调用核心函数copy_process复制进程。copy_process分配新task_struct内存页,复制父进程任务结构,设置子进程寄存器状态和内存空间,并更新文件引用计数。最终子进程获得独立资源,fork返回子进程PID(父进程)或0(子进程)。整个过程涉

2025-11-15 09:39:35 723

原创 Linux rcu机制

RCU同步机制学习摘要 RCU是一种针对读多写少场景优化的Linux内核同步机制。核心思想是将更新分为移除和回收两阶段:先移除数据引用,待所有读取者完成临界区后再回收内存。关键特性包括:发布-订阅机制(使用rcu_assign_pointer确保写入顺序)、读端临界区保护(rcu_read_lock/unlock通过关闭抢占实现)以及宽限期等待(synchronize_rcu)。主要API包括:rcu_assign_pointer保证写入可见性、rcu_dereference安全获取指针值、synchron

2025-11-08 10:17:53 253

原创 Linux通知链源码剖析

Linux内核通知链机制是一种用于子系统间事件通知的机制,主要通过函数链表实现。当事件发生时,链表中所有注册的回调函数会被执行。通知链分为四种类型:原始通知链(性能最高)、阻塞通知链(进程上下文加锁)、原子通知链(中断上下文加锁)和SRCU通知链(读写并发场景)。核心结构包括notifier_block(回调函数和优先级)和各类通知链头。API提供注册/注销函数,按优先级排序插入,并支持事件触发时的回调链式调用。该机制适用于内核子系统间通信,但不支持内核与用户空间通信。

2025-10-25 16:41:51 164

原创 Linux对象管理机制

在linux内核中,采用对象机制来组织和管理系统单元。kobject表示基本对象单元,kset用来管理一组kobject,ktype用来定义对象行为。此图来源于互联网。

2025-10-14 20:29:58 303

原创 Linux0.12下的定时器中断

Linux0.12定时器中断机制解析:系统通过8253定时器设置10ms触发一次中断(HZ=100),中断处理流程包括保存寄存器状态、更新系统时间计数(jiffies),并调用do_timer函数处理任务调度、硬盘超时检测、屏幕息屏等定时任务。内核根据当前特权级(用户态/内核态)统计进程时间,时间片耗尽时触发进程调度。该机制实现了系统基本的时间管理和任务调度功能。

2025-10-04 13:04:34 248

原创 Linux0.12中schedule函数的下详细注释

摘要:本文展示了Linux早期版本的任务调度实现,包括switch_to宏和schedule函数。switch_to宏通过汇编指令实现任务上下文切换,并处理协处理器状态。schedule函数采用轮转调度算法,遍历任务列表检查超时、信号等状态,选择counter最大的就绪任务执行。当没有任务就绪时,重新计算所有任务的时间片(counter = counter/2 + priority)。最后通过switch_to宏切换至选中任务。该实现体现了Linux早期简单的任务调度机制。

2025-10-04 10:09:17 230

原创 Linux0.12中系统调用源码分析

本文档详细分析了 Linux 0.12 内核的系统调用路径,以 fork() 为例说明从用户空间触发系统调用到内核处理的完整过程。首先通过 _syscall0 宏展开为内联汇编,执行 int 0x80 软中断,将系统调用号存入 eax 寄存器。中断触发后 CPU 通过 IDT 跳转到 system_call 入口,保存寄存器状态并检查系统调用号有效性,再通过 sys_call_table 调用对应处理函数(如 sys_fork)。处理完成后保存返回值到 eax 并恢复寄存器,最终返回用户空间。整个过程展示了

2025-09-27 12:26:55 185

原创 Linux0.12的中断处理过程源码分析

本文介绍了Linux 0.12内核中的中断处理机制。中断处理分为汇编部分(asm.s)和C函数部分(traps.c),使用进程内核态栈。初始化时,boot/head.S中定义了一个256项IDT表,并全部设置为默认中断处理函数;随后在traps.c中重新设置特定中断的处理函数。以除0异常为例,CPU会通过IDT找到_divide_error处理函数,该函数会保存寄存器状态、切换内核数据段、调用C处理函数_do_divide_error,最后恢复寄存器并通过iret指令返回。中断处理过程体现了内核态与用户态的

2025-09-21 19:46:40 323

原创 Linux0.12设置中断描述符表

Linux 0.12内核通过_set_gate宏实现中断描述符表设置,该宏使用内联汇编将处理函数地址和属性信息写入8字节门描述符。内核提供了三个封装函数:set_intr_gate(中断门,特权级0)、set_trap_gate(陷阱门,特权级0)和set_system_gate(系统门,特权级3)。门描述符结构包含16位段选择子、32位偏移地址和16位属性字(含类型和特权级)。_set_gate宏通过寄存器操作将参数组合成完整的门描述符格式,并写入IDT对应位置。

2025-09-13 10:28:49 309

原创 linux0.12 内存管理

该文章主要介绍了Linux系统中的内存管理机制。首先说明了物理内存的划分结构,包括内核模块、高速缓冲区和主内存区。其次详细解释了四种内存地址类型:虚拟地址、逻辑地址、线性地址和物理地址。文章重点阐述了内存分段机制的工作原理,包括实模式和保护模式下的寻址方式,以及全局描述符表(GDT)和局部描述符表(LDT)的作用。最后介绍了内存分页管理机制,说明了如何通过分页将线性地址转换为物理地址,并提到CR3寄存器保存当前页目录表的基地址。这些机制共同构成了Linux系统的虚拟内存管理框架。

2025-09-07 09:53:32 616

原创 linux0.12 head.s代码解析

本文摘要了Linux 0.11内核启动过程中32位初始化代码head.s的主要功能。该代码首先初始化IDT和GDT表,设置256个中断门默认处理函数;检查A20地址线是否启用;配置数学协处理器;设置4个页表来映射0-16MB物理内存,并启用分页机制;最后将main函数参数压栈后跳转执行。源码详细展示了内存管理单元(MMU)初始化、中断描述符表设置、分页机制建立等关键步骤,这些操作为后续内核运行提供了必要的硬件支持环境。

2025-09-03 20:13:41 214

原创 Linux0.12 setup.S代码解析

本文介绍了Linux 0.12启动过程中setup.S模块的核心功能:1)收集硬件信息(内存、显卡、硬盘等)并存储在0x90000~0x901FF区域;2)将内核从0x10000重定位到0x00000,设置IDT和GDT;3)重新映射中断控制器,避免与保留中断冲突;4)最后进入保护模式并跳转到0x00000执行。整个流程完成了从实模式到保护模式的关键转换,为后续内核加载做好准备。代码展示了早期Linux系统启动时对硬件信息的获取和初始化过程。

2025-08-31 10:19:38 173

原创 Linux0.12 bootsect.S代码解析

这段代码是Linux 0.11的bootsect.s引导程序,主要功能包括:1) 将自身从0x7C00移动到0x90000;2) 加载setup模块到0x90200;3) 加载系统内核到0x10000;4) 检测根设备类型(1.2M/1.44M软盘)。代码首先修改磁盘参数表支持18扇区/磁道,然后通过BIOS中断读取磁盘数据。若读取失败会显示错误并重试,成功加载后跳转到setup程序继续启动过程。整个过程采用段寄存器管理内存地址,确保内核加载到正确位置。

2025-08-28 10:06:39 171

原创 柔性数组介绍

在结构体中存放一个动态长度的字符串有两种方法:指针和柔性数组。柔性数组:运行结果

2022-06-13 15:26:58 225

原创 I/O多路转接

什么是I/O多路转接?对大量的文件描述符进行I/O事件监控。IO事件包括:可读事件、可写事件、异常事件函数selectint select( int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout );参数nfds:在下面3个文件描述符集中找到最大的文件描述符,然后+1。参数readfds和writefds和exceptfds:描述符集的指针,可以将它看成是一个数组。这3

2022-05-20 17:46:28 2688

原创 getline

getlinegetline源码,根据源码编写自己的getline函数,只保留核心功能,。#define GETDELIM_GROWBY 64/** * @brief 读取一行数据 * * @param lineptr 数据存放缓冲区 * @param n lineptr的大小 * @param stream * @return ssize_t 成功返回读取到的数量,失败返回-1 */ssize_t mygetline( char **lineptr, size_t *n, FIL

2022-05-01 21:01:14 799

原创 文件IO缓冲

文件I/O缓冲系统I/O调用和C语言库I/O函数在操作磁盘文件时会对数据进行缓冲介绍read() 和 write() 调用在操作磁盘文件时不会直接发起磁盘访问,而是仅仅在用户空间缓冲区和内核缓冲区高速缓存之间复制数据。在后续某个时刻,内核会将其缓冲区的数据刷新到磁盘。当把缓冲区中的数据取完,这时内核会将文件的下一段内容读入缓冲区。采用这一设计,使 read() 和 write() 调用的操作更为快捷。Linux 内核对缓冲区的大小没有固定上限。受限于:物理内存总量处于其他目的对物理内存的需求

2022-04-24 12:12:14 303

原创 Linux内存映射

内存映射按文件分:文件映射:将一个文件的一部分直接映射到调用进程的虚拟内存中匿名映射:没有对应文件,被映射的分页会初始化为0按权限分:私有映射:写时复制,变更不会再底层文件进行共享映射:变更发生在底层文件将上面两两组合:私有文件映射:使用一个文件的内容来初始化一块内存区域私有匿名映射:为一个进程分配新的内存共享文件映射:代替 read() 和 write() 、IPC共享匿名映射:实现相关进程实现类似于共享内存进程执行 exec() 时映射会丢失,但通过 fork()

2022-04-20 20:51:06 1787

原创 System V 共享内存

System V 共享内存fork() 创建的子进程会继承其父进程附加的共享内存段API 函数创建或打开共享内存#include <sys/types.h>#include <sys/shm.h>int shmget( key_t key, size_t, int shmflg );参数 key:由 IPC_PRIVATE 或 ftok() 生成的键参数 size:表示需分配共享内存的字节数内核是以系统分页大小的整数被来分配共享内存的,所以会 size 会被提

2022-04-19 10:03:57 261

原创 System V 信号量

System V 信号量API 函数创建或打开一个信号量集#include <sys/types.h>#include <sys/sem.h>int semget( key_t key, int nsems, int semflg );成功返回信号集的标识符参数 key:由 IPC_PRIVATE 或 ftok() 返回的键参数 nsems:创建信号集时:nsems 指定信号量的数量,必须大于0获取信号集时:nsems 必须小于等于集合的大小参数 s

2022-04-16 14:35:30 1239

原创 ELF目标文件分析

ELF目标文件分析源代码#include <stdio.h>int printf( const char* format, ... );int global_init_var = 84;int global_unint_var;void func1( int i ){ printf( "%d\n", i );}int main( void ){ static int static_var = 85; static int static_var2

2022-04-12 16:25:29 462

原创 System V 消息队列

消息队列创建消息队列#include <sys/types.h>#include <sys/msg.h>int msgget( key_t key, int msgflg )成功返回消息队列的标识符,它是消息队列的句柄。失败返回-1和设置error参数 key 是一个键,用于生成唯一的标识符。可由 IPC_PRIVATE或 ftok() 生成。参数 msgflg 是权限位和下面这些位组成:IPC_CREAT:没有于指定 key 对应的消息队列,则新建一个I

2022-04-12 10:56:00 775

原创 Keil的编译器优化级别和调试视图

Keil的编译器优化级别和调试视图Compiler User Guide: Compiler optimization levels and the debug view编译器执行的精确优化取决于选择的优化级别,以及您是针对性能还是代码大小进行优化。编译器支持以下优化级别:0最小优化。 关闭大多数优化。 启用调试时,此选项可提供最佳调试视图,因为生成的代码的结构直接对应于源代码。 所有干扰调试视图的优化都被禁用。 特别是:断点可以设置在任何可到达的点上,包括死代码。变量的值在其范围内的任何地

2021-11-20 11:41:56 3017

原创 vTaskNotifyGiveFromISR源码分析

以STM32平台为例,在STM32中数值优先级越低,逻辑优先级越高。 void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) { TCB_t * pxTCB; uint8_t ucOriginalNotifyState; UBaseType_t uxSavedInterruptStatus; configASSERT( xTaskToNotify ); (

2021-11-18 20:24:17 1168

原创 FLASH预取

FLASH预取在stm32中,我们的代码都是放在flash中的,内核是M3,内核要读flash中的code,它是一条一条读一条一条执行的。读完第一条,还没读第二条代码时,内核先会把将要读的读的第二条代码先取好,放好等待它去读,这个过程称为预取指。Cortex处理器采用的是三级流水线的哈佛结构,一条指令的执行分为:取指阶段(Fetch stage)、译码阶段(Decode stage)、执行阶段(Execute stage)。CPU 通常需要 4 个周期( 72Mhz下, 2 个等待周期)读取 64

2021-11-09 22:05:09 3822

原创 3. 无重复字符的最长子串

滑动窗口解题思路left 和 right 都处于最左边指向right 不断向右遍历直到末尾(在遍历期间遇到了重复的元素 right 就停下来,然后 left 开始向右遍历直到删除重复的元素,然后 right 继续向右遍历)在遍历期间不断更新最长子串的长度代码class Solution {public: int lengthOfLongestSubstring(string s) { int ret = 0; int left = 0;

2021-08-22 13:45:51 149

原创 LVGL v7移植到ARM平台

本次移植的是LVGL v7.110硬件平台:野火IMX6ULL参考博客:实践分享 | 基于framebuffer的lvgl的移植使用_嵌入式大杂烩-优快云博客⭐建立一个lvgl项目 — 百问网LVGL系列教程 1.0 文档 (gitee.io)1 下载所需要的仓库git clone git://github.com/lvgl/lvgl.git -b v7.11.0 #官方图形库git clone git://github.com/lvgl/lv_drivers.git -b v7.11..

2021-06-12 19:49:17 1053 1

原创 freetype显示中英文

freetype显示中英文参考博客:04.freetype显示中文_//查无此人的博客-优快云博客_freetype 中文freetype的安装与使用_explore_world的博客-优快云博客_freetype安装 使用freetype来显示中文汉字和英文字符_mlove编程-优快云博客3.数码相框-通过freetype库实现矢量显示 - 诺谦 - 博客园 (cnblogs.com)1 安装freetypefreetype-2.10.0.tar.gz链接:https://pan.b

2021-05-15 16:31:17 1311 2

原创 modbus-tk学习笔记

对于modbus ASCII 模式,使用的是高位字节在前,低位字节在后。使用LRC校验。对于modbus rtu 模式,使用的是低位字节在前,高位字节在后。使用CRC校验。参考博客:modbus 入门篇,不冗长,很好理解!MODBUS学习笔记——modbus tk modbus TCP主机实现_物联网 IoT 经验分享-优快云博客_modbus_tkmodbus协议中的寄存器理解0.前言modbus是一种古老但是高效的应用层协议。在嵌入式和PC机领域有多种方法实现modbus协议栈,mo.

2021-05-15 15:38:45 7691 5

原创 AT24C02数据存储

一、引脚说明WP:当该引脚接GND时可读可写,接Vcc只读。二、器件地址开发板原理图:所以器件写地址为0xA0,读地址为0xA1。三、写操作

2021-01-15 19:17:51 1234

原创 模拟IIC(HAL库)

有关IIC的详细教程请看博主的另一篇文章本文只展示HAL库代码 /** * @brief 初始化IO * @param 无 * @retval 无 */void IIC_GPIO_Config(void){ GPIO_InitTypeDef GPIO_InitStruct; IIC_GPIO_CLK_ENABLE(); GPIO_InitStruct.Pin = IIC_SCL_PIN | IIC_SDA_PIN;

2021-01-06 17:24:12 2958

原创 模拟IIC(基于STM32)

话不多说,直接讲代码GPIO配置STM32的8种引脚模式void IIC_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOx,ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Pin = IIC_SCL_Pin|IIC_SDA_Pin; GP

2021-01-04 10:55:48 7307 4

原创 Makefile的使用

什么是MakefileMakefile是编译工程的工具,包含以下两部分:make工具:可以找出项目里修改过的文件和受修改文件影响的其他文件进行单独编译,避免重复编译。Makefile文件:存放文件之间的依赖关系和编译规则

2020-12-08 16:23:53 597

原创 Ubuntu无法进入共享文件夹

项目场景:使用Linux的cd命令进入共享文件夹问题描述:提示权限不够bash: cd: dir_share/: 权限不够原因分析:使用ls -l命令查看共享文件夹权限drwxrwx--- 1 root vboxsf 0 12月 4 23:30 dir_share得知dir_share文件夹属于root用户,vboxf用户组,而其他用户没有权限,所以我们无法进入共享文件夹。解决方案:将自己登录的用户,添加到vboxsf组中。sudo adduser 你的用户名 vb

2020-12-05 00:29:23 1987

模拟IIC-HAL库.7z

STM32基于HAL库的模拟IIC

2021-01-06

基于STM32F103的模拟SPI

基于STM32F103的模拟SPI

2020-10-18

OLED(模拟SPI).7z

基于STM32F103的0.96寸OLED显示

2020-11-10

32读取W25Q64整数和小数(模拟SPI).7z

32读取W25Q64整数和小数 模拟SPI

2020-10-30

矩阵按键1~16串口显示.zip

F103ZET6的4X4矩阵键盘,对应1-16,并且可以串口发送到电脑显示,

2019-08-12

S3C2440全套中文手册.7z

S3C2440全套中文手册

2020-08-07

HC05蓝牙模块.7z

HC05与串口2进行通信,串口1用于打印到电脑的串口调试助手,使用前请确保USART2的波特率与HC05蓝牙波特率保持一致 PB6用于连接Key按键

2020-06-04

空空如也

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

TA关注的人

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