- 博客(46)
- 收藏
- 关注
原创 操作系统(Linux Kernel 0.11&Linux Kernel 0.12)解读整理——内核初始化(main & init)之内存的划分
MMU:内存管理单元(Memory Management Unit)完成的工作就是虚拟地址到物理地址的转换,可以让系统中的多个程序跑在自己独立的虚拟地址空间中,相互不会影响。程序可以对底层的物理内存一无所知,物理地址可以是不连续的,但是不妨碍映射连续的虚拟地址空间。Linux 内核的内存管理程序采用了分页管理方式。它利用页目录和页表结构处理内核中其他部分代码对内存的申请和释放操作。内存的管理是以内存页面为单位进行的,一个内存页面是指地址连续的 4K 字节物理内存。
2025-01-25 12:07:44
775
原创 操作系统(Linux Kernel 0.11&Linux Kernel 0.12)解读整理——内核初始化(main & init)之控制台工作
在 Linux 内核中,字符设备主要包括和,对这些设备的输入输出涉及控制台驱动程序,这包括keyboard.S 和程序 console.c,还有终端驱动程序与上层程序之间的接口部分。终端驱动程序用于控制终端设备,在终端设备和进程之间传输数据,并对所传输的数据进行一定的处理。用户在键盘上键入的原始数据(Raw data),在通过终端程序处理后,被传送给一个接收进程;而进程向终端发送的数据,在终端程序处理后,会被显示在终端屏幕上或者通过串行线路被发送到远程终端。
2025-01-25 11:33:06
1150
原创 操作系统(Linux Kernel 0.11&Linux Kernel 0.12)解读整理——内核初始化(main & init)之进程调度的开始
是一个可执行的文件,而是一个执行中的程序实例。利用分时技术,在Linux操作系统上同时可以运行多个进程。分时技术的基本原理是把 CPU 的运行时间划分成一个个规定长度的,让每个进程在一个时间片内运行。当进程的时间片用完时系统就利用调度程序切换到另一个进程去运行。因此实际上对于具有单个 CPU 的机器来说某一时刻只能运行一个进程。但由于每个进程运行的时间片很短(例如 15 个系统滴答=150 毫秒),所以表面看来好象所有进程在同时运行着。
2025-01-23 14:12:32
932
原创 操作系统(Linux Kernel 0.11&Linux Kernel 0.12)解读整理——内核初始化(main & init)之缓冲区的管理
当一个程序需要读取硬盘上的一个逻辑块时,就会向提出申请。而请求读写的程序进程则进入睡眠等待状态。缓冲区管理程序首先在缓冲区中寻找以前是否已经读取过这块数据。如果缓冲区中已经有了,就直接将对应的缓冲区块头指针返回给程序并唤醒等待的进程。若缓冲区中还不存在所要求的数据块,则缓冲管理程序就会调用低级块读写函数,向相应的块设备驱动程序发出一个读数据块的操作请求。该函数会为此创建一个请求结构项,并插入请求队列中。
2025-01-23 12:05:06
1366
原创 操作系统(Linux Kernel 0.11&Linux Kernel 0.12)解读整理——内核初始化(main & init)之硬盘初始化
对和块设备上数据的读写操作是通过进行的。内核每次读写的数据量以一个(1024 字节)为单位,而块设备控制器则是以(512字节)为单位访问块设备。在处理过程中,内核使用了来顺序地缓冲一次读写多个逻辑块的操作。具体的,当一个程序需要读取硬盘上的一个逻辑块时,就会向缓冲区管理程序提出申请。而请求读写的程序进程则进入睡眠等待状态。缓冲区管理程序首先在缓冲区中寻找以前是否已经读取过这块数据。如果缓冲区中已经有了,就直接将对应的缓冲区块头指针返回给程序并唤醒等待的进程。
2025-01-22 11:34:39
1008
原创 操作系统(Linux Kernel 0.11&Linux Kernel 0.12)解读整理——块设备驱动之读取硬盘上的文件
文件读取在高版本的linux是一个复杂无比的流程。一个进程(task_struct)读取一个文件会被存储在自身的file_struct结构中,对应打开文件的索引,然后陷入内核,系统调用,内核态调用最终要调用通用块(理解为硬盘之上)提供的读取接口,向硬盘发请求(request),然后IO调度系统去按照高效的算法调度,磁头去读取。其中的大前提基础是进行request结构初始化其中的块设备操作主要涉及下面这个接口读取硬盘数据到内存中,是操作系统的一个基础功能。读取硬盘需要有。
2025-01-22 11:01:27
976
原创 操作系统(Linux Kernel 0.11&Linux Kernel 0.12)一手资料解读整理——引导启动程序(Boot)之内存的映射机制
上电启动流程如下:boot/目录下的三个汇编语言文件(bootsect.S 和 setup.S 是实模式下运行的 16位代码程序,采用近似于 Intel 的汇编语言语法,并且需要使用 8086 汇编编译器和连接器 as86 和 1d86。而 head.s 则使用一种 AT&T 的汇编语法格式,并且运行在保护模式下,需要用 GNU 的 as(gas)汇编器进行编译)。操作系统第一阶段如下:(剖析操作系统,一开始就是面向芯片编程,按照芯片手册,当涉及了进程调度则面向多任务处理)
2025-01-21 10:39:55
900
原创 pip 安装 transformers报错处理 error: subprocess-exited-with-error × Preparing metadata (pyproject.toml)...
在conda 虚拟环境中使用 python 的 pip install transformers报错处理 (当前使用的是python3.7.13)(分析可能的原因是依赖包冲突,导致依赖包冲突的原因可能是缺失关键包,版本兼容等问题)由于Hugging Face的transformer依赖包是封装比较完整的包,安装导致的缺失关键包,可能是conda虚拟环境的Python版本优化了部分包。
2025-01-21 10:01:10
1767
原创 Linux系统编程——IO多路复用(select,poll,epoll)详解及应用场景使用分析汇总
IO多路复用是一种操作系统技术,旨在提高系统处理多个输入输出操作的性能和资源利用率。与传统的多线程或多进程模型相比,IO多路复用避免了因阻塞IO而导致的资源浪费和低效率问题。它通过将多个IO操作合并到一个系统调用中,允许程序同时等待多个文件描述符(如sockets、文件句柄等)变为可读或可写状态,然后再执行实际的IO操作。在IO多路复用的实现中,常用的系统调用包括select()、poll()和epoll()。
2024-12-15 14:07:16
1337
原创 数据结构与算法汇总整理篇——哈希表(细节学习及各容器选取的思考)
散列表(Hash table,也称哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表(数组+链表 或 数组+树)。hashtable(key,value) 就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。
2024-12-14 13:41:54
1260
原创 嵌入式处理器程序设计(处理思路及经验篇)——开发必备的特定设计思维及POSIX标准
嵌入式系统的核心是嵌入式处理器。嵌入式处理器一般划分为如下类型:嵌入式系统分层结构一般可如下:两层结构:硬件层、应用层(软件层) 诸如: MCU裸机系统三层结构:硬件层(原厂芯片用库函数封装驱动)、操作系统层、应用层 诸如: MCU的RTOS系统。
2024-12-11 16:25:21
1214
原创 什么是CPU的上下文切换(context switch的统计与进程排查)
由于Linux是一个多任务的分时操作系统,能够支持远大于CPU数量的任务同时运行。实际上,对于单个CPU核,其处理数据是串行的,同时,这些任务实际上并不是真的在同时运行,而是由CPU进行调度,将时间分片,每个任务占用1个时间片,通过轮流的方式运行,但由于时间片粒度非常小,而CPU速度非常高,造成多任务同时运行的错觉。(就比如排队登记,只有一个登记处的操办人员,组织人员会在登记处排几个队列,每个队列头部数出10个人构成一组。
2024-12-11 15:26:26
1020
原创 程序设计的难点讨论——技术性与思维性和集思广益的并存
程序设计的根本性难点不外乎是和(技术与思维的铸就)。程序,专业的说法,是由数据结构和算法共同组成的用计算机语言表示的逻辑。逻辑和数学实则可以归为算法。前者强调的是算法的顺序性,后者强调的是算法的运算性(复杂度)。绝大部分的程序员做的其实都是建立在已有设施上的劳动密集型工作。而既然是劳动密集型,那么就有一个问题需要解决,即一个难点:分工。广义层面上的分工,下至模块、框架、接口、设计模式、上至IEEE标准说到底都是为了解决这个问题--分工。
2024-12-09 15:05:21
830
原创 C实用型语法技巧与功能——面向过程的语法实现面向对象的编程效果相关细节
可以指定数组的元素来进行初始化。特别是当需要根据一组#define来保持某种映射关系的同步更新时。
2024-12-09 14:27:26
924
原创 数据结构与算法汇总整理篇——数组与字符串&&双指针与滑动窗口的联系学习及框架思考
(2) if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,⽽寻找区间是左闭右开区间,所以right更新为middle,即:下⼀个查询区间不会去⽐较nums[middle](2) if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]⼀定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1。
2024-10-27 20:23:46
952
原创 软硬件开发面试问题大汇总篇——针对非常规八股问题的提问与应答(代码规范与生态管理)
DMA(Direct Memory Access):DMA 是一种允许外部设备(如硬盘、网络适配器等)直接访问主内存而不通过 CPU 的技术。这样可以在数据传输时释放 CPU,让其处理其他任务,提高系统效率。FIFO(First In, First Out):FIFO 是一种数据结构,用于缓存数据。按照“先进先出”的原则,最早进入缓冲区的数据会最先被读取。FIFO 通常用于实现队列或缓冲区。为了确保安全性和效率,可以为每个分区定义访问权限。例如:只读/可写:对于固件区域,可设为只读;
2024-10-27 19:29:21
1259
原创 软硬件开发面试问题大汇总篇——针对非常规八股问题的提问与应答
软硬件开发,从微控制器编程到复杂的嵌入式系统开发,离不开下位机、操作系统、上位机等,涵盖范围很广。
2024-10-26 21:07:13
1043
原创 Orange Pi(H616)出现wiringPiSetup错误解决方案;wiringpi Unable to open /dev/mem or /dev/gpiomem: Permission de
( 当使用自写脚本的形式编译 H616的可执行程序时,出现无法打开设备,访问权限不够 )(可能 build.sh 执行权不够 (尝试给其权限755 776 777均出错))
2024-10-25 12:43:11
417
原创 算法汇总整理篇——贪心与动态规划学习及框架思考
如果某⼀问题有很多重叠⼦问题,使⽤动态规划是最有效的动规是由前⼀个状态推导出来的,⽽贪⼼是局部直接选最优的 不同路径IIdp[i][j] 表示到达位置ij共有多少中方法整数拆分dp[i] 表示拆分数字i的乘积最大值不同的二叉搜索树dp[n] n个节点组成的节点值从1到n互不相同的二叉搜索树数量 dp[i] += dp[以j为头结点左子树节点数量] * dp[以j为头结点右子树节点数量]num i, root j : left j-1 right i-j j相当于是头结点的元
2024-10-25 10:27:43
968
原创 项目管理必备Git使用及关键指令(总体结构 + 必要步骤)教你如何协同开发
在linux的Ubuntu发行版,执行以下命令即可安装其他系统可以到官方网站进行下载安装Windows系统的安装包阿里巴巴镜像git作为项目管理工具,配置并初始化一个仓库(repository)、开始或停止跟踪(track)文件、暂存(stage)或提交()都是必要环节。
2024-10-24 15:26:00
755
原创 Linux内核——内核源码的探索+教你如何系统认识Linux内核源码树(推荐方式+推荐工具+推荐书目)
全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,该操作系统是由 Linus Torvalds于1991年10月5号首次发布, 它主要受到Minix和Unix思想的启发,是一个。严格地讲,Linux单指操作系统的内核,加上用户空间的应用程序之后,就成为Linux操作系统。
2024-08-25 14:54:23
1215
原创 动态链接库——深入探讨C++程序中.so技术细节和实现方式及C程序中动静态库的区别(+工程分步骤编译库)
在开发中,动态链接库(DLL)和共享对象(Shared Object).so文件的使用成为提升程序灵活性和重用性的关键手段。如下相关工具,一种用于创建可移植共享库的工具。关于动态链接器的更多信息。一个跨平台的构建系统,简化了共享库的管理和构建。无论是提升程序的模块化程度,还是优化资源使用,动态链接都是一种强大的技术手段。
2024-08-25 11:50:48
1334
原创 ARM架构的BootLoader详解——对于Linux与Baremetal(裸机MCU)
BootLoader的启动方式基本如下:stage1程序(汇编)在内存之外的存储介质中对内存空间进行初始化后,再将stage2程序(C)加载到内存中执行。stage2。
2024-08-23 12:11:10
2204
6
原创 PWM驱动电机系列——PID控制 (各电机设备之间的驱动差异及区别)自动控制系统的性能指标
对于速度跟踪控制来说,增量式 PID 更加适合,因为它直接计算速度变化量。相比之下,位置式 PID 需要计算绝对速度误差,在速度跟踪控制中可能会产生超调和振荡等问题。
2024-08-23 11:28:45
2699
原创 C的动态内存管理 free()和malloc()的简单实现——free()根据内存地址便知释放内存的空间大小(原理详解)
malloc 分配的内存是未初始化的,其中的字节内容是不确定的(可能是随机值)。如果内存分配失败,malloc 返回一个空指针 NULL,可以通过检查返回值来判断是否分配成功。calloc 分配的内存会被初始化为全0。calloc 在分配失败时会自动抛出错误(异常),可以使用异常处理机制来捕获和处理错误。realloc 当malloc函数或者calloc函数申请的空间或者数组的空间不够大或太大时就可以用realloc函数对空间的大小进行调整。
2024-08-21 11:25:22
1044
原创 Linux设备驱动——字符设备的高阶驱动实现及关键要素之阻塞型I/O用法详解(休眠与唤醒机制)
指当进程/线程执行某个需求时,因为当下无法立即满足请求,而使其进程或线程阻塞。优点:在某些情况下,阻塞型 I/O 可以更有效地利用系统资源。在一些高负载场景下,可以避免频繁的上下文切换,降低系统开销。而且阻塞型I/O的编程模型通常比较直观和易于理解。代码顺序执行(算作一个同步过程),不需要太多复杂的逻辑来处理异步操作和事件回调。开发经验:(驱动程序应该(默认)阻塞型进程,将其置入休眠状态直到请求可继续)
2024-08-21 10:50:16
1148
原创 C指针汇总——藏在数组名与指针之间的异同及使用细节
数组指针是一个指针变量,占有内存中一个指针的存储空间;指针数组是多个指针变量,以数组的形式存储在内存中,占有多个指针的存储空间。注意。
2024-08-19 15:57:30
812
原创 Linux设备驱动——字符设备的基本驱动实现及关键要素(体系地认识文件与驱动)
字符(char)设备是个能够像字节流(类似文件)一样被访问的设备,比如字符终端(/dev/console)和串口(/dev/ttys0),它们可以通过文件系统节点来访问,大多数字符设备是一个个只能顺序访问的数据通道。字符驱动设备程序适合于大多数简单的硬件设备,且比起块设备或网络驱动设备程序的架构相对简洁。在深入了解设备驱动程序时,从字符设备开始剖析可以更好地理解内核的工作过程。
2024-08-19 15:21:15
948
原创 Linux设备驱动——模块的构造、运行与设计 与众不同的hello world与点灯
编写一个Linux下的设备驱动,首先要准备好对应内核版本的内核源码树文件。该系列的全部文章都以嵌入式系统的ARM-Linux的环境进行阐述,并以交叉编译的方式在主机Ubuntu20.04系统上编译和ARM开发板上跑测 (E2000Q、H616、或者IMX6ULL看情况交叉着使用) 关于交叉编译的配置,以往的文章中有作介绍,这里不再赘述。驱动程序一般要执行两类任务1.模块中的某些函数作为系统调用的一部分而执行2.某些函数则负责中断处理。
2024-08-11 21:25:03
1346
原创 Linux设备驱动浅谈 利用Linux内核接口可以实现自定义模块机制
接触编程,大家应该都有这样一个疑惑,我们写的应用程序一执行,便在操作系统上工作,其原理是(当程序一执行,它便成为一个操作系统上的进程,然后由操作系统进行管理),那如果我们写的程序要让某些硬件设备工作呢,那又是如何工作的,这对于应用开发的人员而言,一般不作太深入的了解,但是在计算机体系中,它是不可或缺的一部分。在实际的项目开发中以Linux环境为多数,此图诠释了计算机软件层和硬件层的组成,本文将对下面这个结构不断拆解,最后回答这个问题——如何用程序让硬件设备工作。
2024-08-10 16:57:13
1258
原创 回溯函数(算法)杂谈 -----可主动控制撤回逻辑处理的递归函数
回溯,对接触了算法的人而言,并不陌生,其实严谨地说回溯函数就是递归函数,只不过在使用上,人们将它的一些细节抽离出来,进而演化出了所谓的回溯,在算法导论中,与其相关的被称为“回溯搜索算法”。回溯本质是递归的副产物,只要有递归调用就会有回溯。回溯法也经常和二叉树或N叉树遍历,深度优先搜索混在一起,因为这两种方式的简单实现都是用了递归(当然可以使用数据结构的栈模拟递归,来设计搜索遍历算法)。
2024-08-10 11:53:20
1014
原创 函数指针与指针函数(浅谈) C也能实现面向对象编程思维的关键
函数指针的本质是一个指针,该指针的地址指向了一个函数,即指向函数的指针。函数的定义是存在于代码段,因此,每个函数在代码段中,也有着对应的入口地址,函数指针就是指向代码段中函数入口地址的指针。/*return_type 为返回类型,ptr为指针变量,代表的是指向目标函数的指针args为形参列表,*ptr即为函数。*/初始化方式a : b;//函数指针的定义//函数指针的另一种定义方式,不过不建议使用//也可以使用这种方式定义函数指针//函数指针初始化//函数指针的调用。
2024-08-06 20:19:10
975
原创 W25Q128 spi-flash HAL库驱动详解
W25Q128是华邦公司推出的一款容量为 128M-bit(1byte == 8bit,相当于 16M-byte)的 SPI 接口的 NOR Flash 芯片(NOR Flash:一种非易失性存储器,它可以在断电或掉电后仍然保持存储的数据,被广泛应用于长期数据存储。有容量大,可重复擦写、按“扇区/块”擦除的特性。Flash的物理特性:只能写0,不能写 1,写1靠擦除。这一特性对后续编程,实现控制非常重要相应的还有其他型号。
2024-08-06 15:03:43
1977
原创 编译报错 aarch64-none-linux-gnu-gcc: error: unrecognized argument in option ‘-mabi=apcs-gnu’ aarch64-non
交叉编译工具报错,大概意思是:架构不匹配我的交叉编译工具环境的配置为此时,arch环境变量,表示的是不同的计算机架构,此时为arm架构,但是工具链是arm64体系结构的。
2024-08-05 17:23:26
1357
1
原创 0.96寸(128*64) OLED(SSD1306) 中英显示+任意图像显示
(现使用的比较多的是4线SPI控制和 I2C控制,接下来将以I2C控制为例子)
2024-08-05 14:13:22
1255
原创 排序算法与字符串操作函数实现 ( 细节系统整理篇 )
( 与strcpy()函数不同的是,该函数不会检查任何终止字符(如'\0'),而总是精确的拷贝参数传入的字节数,当想拷贝一个整型数组/结构体/枚举常量等strcpy()函数无法拷贝的数据时,可以考虑使用memcpy()函数来完实现这一诉求,当然,想要使用memcpy()函数拷贝字符串也是可以的 )( 例如:比较字符串str1和str2 strcmp(str1,str2) 如果返回值小于 0,则表示 str1 < str2。若str2是str1的子串,则返回str2在str1的首次出现的地址;
2024-05-07 17:28:47
835
原创 warning: initialization of ‘int (*)(int, int)’ from incompatible pointer type ‘void (*)(int, int)’警告
这个报错的原因是类型不匹配。具体来说,代码中定义了一个函数指针变量,它的类型是 int(*)(int,int),但是在赋值时,右侧的函数类型是 void(*)(int,int),两个类型不匹配,导致编译器报错。
2024-04-30 17:13:06
424
1
原创 通信协议篇 ( 常用的协议快速入门)
IIC全称Inter-Integrated Circuit (集成电路总线) 是由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备( 驱动FRAM、E2PROM、OLED等 )。IIC属于方式( 每个连接到总线上的设备都有唯一的地址,任何设备既可以作为主机也可以作为从机,但同一时刻只允许有一个主机。IIC 标准是一个具有冲突检测机制和仲裁机制的真正意义上的多主机总线,它能在多个主机同时请求控制总线时利用仲裁机制避免数据冲突并保护数据。( 特点: 简单性、有效性、 多主控)
2024-03-11 20:40:22
2412
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人