- 博客(277)
- 资源 (2)
- 收藏
- 关注
原创 交叉编译chrony时钟同步程序并移植到下位机联网同步时间总结
本文介绍了在无电池存储时间的ARM架构开发板上实现时间同步的解决方案。由于开发板运行裁剪版Ubuntu系统且无包管理工具,作者通过在上位机交叉编译chrony时间同步程序并移植到下位机。详细说明了配置步骤:包括选择NTP服务器、设置时钟层级、处理时间偏差等配置文件修改,以及网络连接配置方法。最后通过执行chrony程序成功实现时间同步,解决了定时任务错乱、日志时间戳不一致等问题。该方案适用于嵌入式系统时间同步需求,尤其针对无法直接使用apt安装软件的特殊环境。
2025-10-13 16:45:08
916
原创 16. SPDK应用框架
SPDK提供了一套编程框架来优化用户态NVMe驱动的性能,包括CPU核心绑定、线程管理、无锁通信和I/O处理模型。框架采用Reactor线程和Poller机制执行任务,通过事件环实现高效线程通信,并遵循"运行直到完成"的I/O处理原则,避免跨线程操作带来的性能损耗。该框架可帮助开发者构建高性能存储应用或改造现有应用适配SPDK驱动。
2025-10-09 16:51:52
799
原创 15. SPDK NVMe驱动
本文介绍了存储接口从AHCI到NVMe的演进过程,重点分析了SPDK用户态驱动技术。主要内容包括:1)传统AHCI接口逐渐成为SSD性能瓶颈,NVMe应运而生;2)SPDK通过用户态驱动(UIO/VFIO)、DMA优化、大页技术等提升性能;3)用户态驱动采用异步轮询、无锁化设计等优化手段;4)SPDK支持多进程共享设备时的资源管理机制。文章详细阐述了这些技术的实现原理和优势,为高性能存储系统开发提供了重要参考。
2025-10-09 15:10:50
1057
原创 14. 初识 SPDK
SPDK是由英特尔发起的,用于加速NVMe SSD作为后端存储使用的应用软件加速库。这个软件库的核心是用户态、异步、轮询方式的NVMe驱动。相比内核的NVMe驱动,SPDK可以大幅降低NVMe command的延迟,提高单CPU核的IOps,形成一套高性价比的解决方案,如SPDK的vhost解决方案可以被应用到HCI中加速虚拟机的NVMe I/O。SPDK LOGOSPDK最早的项目代号为WaikikiBeach,全称是,2015年开源以后,改为SPDK。
2025-09-30 11:12:13
958
原创 13. 初识 NVMe over RDMA
RoCE v2和iWARP的设计初衷都是在传统的以太网技术上实现RDMA,网络层它们都基于IP,只不过在传输层一个选择了UDP,一个选择了TCP。,并定义了一组命令集用于支持命令包、回复包以及数据包的收发,包括RDMA_SEND、RDMA_SEND_INVALIDATE、RDMA_READ和RDMA_WRITE。如果更关注延时而对扩展性要求不高,可以选RoCE,它的应用场景包括连接控制节点与NVMe磁盘阵列的环境,或者只有一到二层交换机的环境。,一旦需要升级则牵一发动全身,故更加适合用于全新搭建的场景。
2025-09-29 17:33:55
837
原创 12. 初识 NVMe over Fabrics
不过由于不同的互联协议本身的特点不同,因此基于各种协议的NVMe over Fabrics的具体实现也是不同的。静态控制器则适用于有不同需要的场景,发起者(Initiator)可以查询一个Fabric端口内部包含的静态控制器各自的能力,然后选择连接到指定的控制器以满足自身的需求。对NVMe而言,这并不是一个好办法。如果把几百块NVMe SSD通过PCIe接口接入一个存储池,每块硬盘还都要满足性能要求,PCIe接口的带宽根本无法满足这个要求,即使满足,所有的数据传输都要通过RC,此时RC的负担将非常的重。
2025-09-29 16:25:19
810
原创 11. NVME SSD 的 Namespace
独享的意思是说只有与之关联的控制器才能访问该NS,别的控制器是不能对其进行访问的,下图左边所示控制器0是不能对NS C进行读写操作的,同样,控制器1也不能访问NS A。同时,我们还可以让一个Nvme有若干个RC,这种情况常用于冗余容错策略:SSD有两个控制器和两个PCIe接口,那么我主机也弄成双主机,一个主机挂了,由另一个主机接管任务,继续执行,如上图右边所示。每个NS是独立的,逻辑块大小可以不同,端到端数据保护配置也可以不同:你可以让一个NS使用保镖,另一个NS不使用保镖,再一个NS半程使用保镖。
2025-09-29 11:33:29
908
原创 10. NVME的访存寻址方式
主机如果想读取 SSD 上的用户数据,同样需要告诉 SSD 需要什么数据,需要多少数据,以及数据最后需要放到主机内存的哪个位置上,这些信息包含在主机向 SSD 发送的读命令中。这个例子中,假设主机需要从SSD中读取13KB的数据,其中真正只需要11KB数据,这11KB的数据需要放到3个大小不同的内存中,分别是3KB、4KB和4KB。段描述符,SGL是由SGL段组成的链表,既然是链表,前面一个段就需要有一个指针指向下一个段,这个指针就是SGL段描述符,它描述的是它下一个段所在的空间。
2025-09-29 10:40:09
801
原创 9. NVME与SSD之间的通信
SQ 用于主机发送命令,CQ 用于 SSD 回复命令完成状态;SQ/CQ 可以在主机的内存中,也可以在 SSD 中,但一般在主机内存中(本书中除非特殊说明,不然都是基于 SQ/CQ 在主机内存中进行介绍);Admin 和 I/O 两种类型的 SQ/CQ,前者发送 Admin 命令,后者发送 I/O 命令;系统中只能有一对 Admin SQ/CQ,但可以有很多对 I/O SQ/CQ;I/O SQ 与 CQ 可以是一对一的关系,也可以是多对一的关系;可以赋予 I/O SQ 不同优先级的;
2025-09-22 18:41:50
1008
原创 8. 初识SSD的NVME协议
前几节我们对SSD使用的底层PCIe协议栈进行了简单的概述,现在,我们要具体到SSD所在的应用层来分析其工作原理。也就是 NVME 协议。
2025-09-22 10:47:33
613
原创 7. PCIe的数据链路层 综述
前面看到,一个TLP源于事务层,终于事务层。但TLP不是从发送端一步就跑到接收端的,它经由发送端的数据链路层和物理层,然后是接收端的物理层和数据链路层,最终完成TLP的发送和接收。对于数据链路层和物理层,我们只需要简单了解即可,它不是我们关注的重点。数据链路层位于事务层的下一层,为事务层服务。那么,数据链路层在TLP传输过程中起了什么作用呢?并给每个TLP加上序列号(Sequence Number)和LCRC(Link CRC)
2025-09-19 16:01:23
1003
原创 6. PCIe的TLP路由方法
在前几节,我们对PCIe事务数据包TLP的基本格式、PCIe设备的配置空间进行了总结,我们知道PCIe在传输数据时像网络一样需要通过RC和交换机发送和转发,那么RC和交换机是采用什么策略进行路由转发的?我们现在一探究竟。PCIe 共有 3 种路由方式——基于地址(Memory Address)的路由、基于设备 ID(BDF 序号)的路由,还有就是隐式(Implicit)路由。
2025-09-19 11:17:10
977
原创 5. PCIe的配置和地址空间
在上一节我们对PCIe使用的TLP数据包进行了简述,TLP通过对应的请求ID发送到指定PCIe设备上,如何找到指定的设备?这个时候我们就要查找设备的信息空间进行确定,这段空间被称为 PCIe 的配置空间。整个配置空间就是一系列寄存器的集合,由两部分组成:64B 的 Header 和 192B 的 Capability(能力)数据结构。在PCIe时代,为了兼容PCI,仅将配置空间进行向后延伸,,把整个配置空间由 256B 扩展成 4KB,前面 256B 保持不变。
2025-09-18 18:15:19
1040
原创 Conda 安装 CUDA Toolkit 解决 nvcc 找不到的问题
这是因为 conda install cudatoolkit 只安装了 CUDA 运行时(runtime),并不包含 nvcc 这样的开发工具。在使用 Conda 安装 CUDA 时,很多人会遇到 nvcc: command not found 的问题。本文介绍如何正确安装 nvcc 并配置环境变量,使其正常运行。如果显示 CUDA 版本信息,说明 nvcc 已成功安装。如果 nvcc 输出 CUDA 版本信息,说明安装成功。这会默认安装到 ~/cuda/ 目录。然后运行 nvcc -V 进行验证。
2025-09-14 20:01:06
1189
原创 4. PCIe的分层结构的事务层 TLP事务包分析
PCIe 事务层的TLP(Transaction Layer Packet)包是PCIe协议中用于在主机和外设之间传输数据和控制信息的基本数据单元。它确保了主机和外设之间能够高效、可靠地进行数据交换。通过TLP包,PCIe能够支持多种复杂的操作,如DMA(Direct Memory Access)传输、设备配置等。TLP 主要由 3 个部分组成:Header、数据(可选,取决于具体的 TLP 类型)和 ECRC(End to End CRC,可选)。TLP 都始于发送端的事务层,终于接收端的事务层。
2025-09-08 14:40:43
1021
原创 3. PCIe分层结构的事务层 综述
事务层是PCIe协议栈中负责处理事务的核心层。它通过事务封装、事务管理、事务排序和事务优先级等功能,确保了事务的可靠性和一致性。事务层的组件(如事务生成器、事务接收器、事务队列和事务标签管理器)协同工作,实现了高效、可靠的事务处理机制。
2025-09-04 11:01:14
861
原创 C++ 面试考点 类成员函数的调用时机
的对象,每当程序开始运行,在主函数 main 接受程序控制权之前,就调用构造函数创建全局对象,整个程序结束时,自动调用全局对象的析构函数。2. 对于。
2025-09-02 21:44:40
1192
原创 2. 初识 SSD 的 PCIe协议栈
SSD 已经大跨步迈入 PCIe 时代。PCIe 是 SSD 的一项重要技术,我们有必要对其进行基本的了解。为什么 SSD 要用 PCIe?因为它快,比 SATA 更快。它究竟有多快?我们从 PCIe 的速度开启我们的 PCIe 之旅。PCIe 发展到现在,从 PCIe 1.0、PCIe 2.0,到现在的 PCIe 3.0,速度一代比一代快,如下表所示。这里 x1,x2,x4 等指的是PCIe连接的通道数,PCIe连接可以有多个通道,且它的通信是全双工的。
2025-08-25 15:22:03
1078
原创 1. 初识SSD
SSD(Solid State Drive)即固态硬盘,是一种以半导体闪存(NAND Flash)为介质的存储设备。和传统机械硬盘(Hard Disk Drive,HDD)不同,SSD以半导体存储数据,用纯电子电路实现,不含任何机械设备,这就决定了它在性能、功耗、可靠性等方面和HDD有很大不同。其实SSD的概念很早就有了,但它真正成为主流存储设备还是最近10余年的事情。在2008年初,只有几家公司研发SSD,如今已有上百家大大小小的公司参与其中。
2025-08-25 11:13:25
1350
原创 Linux C 进程间高级通信
在之前学习进程间通信时,我们只接触了一些基础的进程间通信知识。例如管道通信、内存映射等,这些通信方式传值时没有任何问题,当时当传送一些特殊的内存指针或是变量就有可能出问题。由于进程之间彼此是内存隔离的,不能直接访问其他进程的内存空间,每个进程都有自己打开的文件对象或是网络套接字。当进程想把自己已经打开的文件对象分享给其他进程使用,仅通过管道传递一个文件描述符肯定是不行的,它只适用于自己。这个时候我们就可以使用一些特殊的进程通信系统调用,使其可以共享进程内的对象。
2025-07-27 15:46:16
1138
原创 Linux C 网络基础编程
主机字节序(Host Byte Order)依赖于具体计算机系统的架构。在大多数现代计算机系统(如 x86 和 x86_64 架构的机器)中,主机字节序是小端序(Little-Endian),即低位字节存储在低地址处。在某些系统(如某些 PowerPC 架构的机器)中,主机字节序是大端序(Big-Endian)。网络字节序(Network Byte Order)标准的网络通信协议(如 TCP/IP)使用大端序(Big-Endian),即高位字节存储在低地址处。
2025-07-24 17:23:08
704
原创 Linux C 多线程基本操作
我们已经了解进程的基本概念:进程是正在执行的程序,并且是系统资源分配的基本单位。当用户需要在一台计算机上去完成多个独立的工作任务时,可以使用多进程的方式,为每个独立的工作任务分配一个进程。多进程的管理则由操作系统负责——操作系统调度进程,合理地在多个进程之间分配资源,包括CPU资源、内存、文件等等。除此以外,即便是一个单独的应用,采用多进程的设计也可以提升其,改善其。假如在处理任务的过程中,其中一个进程因为死循环或者等待IO之类的原因无法完成任务时,操作系统可以调度另一个进程来完成任务或者响应用户的请求。
2025-07-21 21:10:53
1219
原创 Linux C 进程间通信基本操作
虚拟CPU和虚拟内存的引入保证了进程的一个重要特性就是隔离,一个进程在执行过程中总是认为自己占用了所有的CPU和内存,但是实际在底层,操作系统和硬件完成了很多工作才实现了隔离的特性(比如内核和时钟设备配合实现进程调度)。在多个进程之间,如果需要进行通信的话,隔离特性会造成一些通信的障碍。所以我们需要一些手段来跨越隔离,实现进程间通信(InterProcess Communication,IPC)。
2025-07-18 17:37:41
978
原创 Linux C 进程基本操作
操作系统最初的原型是一种批处理系统(batch):在最开始我们把正在执行的程序称为作业,操作员将所有的作业放在一起,由批处理系统进行读取并交给计算机执行,当一个作业执行完成以后,批处理系统会自动地取出下一个作业。在批处理系统中,存在的最严重的问题是任务执行的过程,会经常需要等待IO操作,这会导致CPU经常性地空闲。为了充分提高CPU的利用率,一种解决方案是引入多道程序设计,在内存当中划分多个区域,每个区域存储一个作业的指令和数据,当其中一个作业在等待IO操作时,另外一个作业可以使用CPU。
2025-07-17 22:51:07
1407
原创 Linux C IO多路复用
IO多路复用(I/O Multiplexing)是一种同时监控多个文件描述符(socket、管道、文件等)的IO状态的机制。当其中任意一个或多个文件描述符就绪(可读、可写或异常)时,内核会通知应用程序,从而避免阻塞等待单个IO操作。在传统阻塞IO模型中,每个IO操作(如readwrite)会阻塞线程直到完成。若需处理多个连接(如Web服务器),必须为每个连接创建一个线程/进程,导致资源浪费(线程上下文切换、内存占用)。IO多路复用通过单线程监控多个IO事件,实现高并发、低资源消耗。
2025-07-15 21:09:11
861
原创 Linux C 管道文件操作
进程间通信:管道文件是实现进程间通信(IPC)的一种简单而高效的方式。它允许进程之间传递数据,而无需复杂的网络编程。命令行组合:在 Shell 中,管道符号()可以将多个命令组合起来,实现复杂的操作。这里,ls -l的输出被传递给grepgrep的输出再被传递给sort。
2025-07-11 16:27:22
1282
原创 Linux C 文件基本操作
在UNIX系统当中,“万物皆文件”是一种重要的设计思想。在传统的定义当中,我们把存储在磁盘当中的数据集合称为文件。而在UNIX的设计当中,文件这个概念得到了进一步泛化,所有满足速度较慢、容量较大和可以持久化存储中任意一个特征的数据集合都可以称为文件,包括不限于磁盘数据、输入输出设备、用于进程间通信的管道、网络等等都属于文件。文件系统是操作系统用于管理文件的子模块。
2025-07-10 21:59:53
828
原创 Linux C 目录流基本操作
本文介绍了Linux目录操作相关函数及其应用。主要内容包括:1. 目录流的概念和操作函数(opendir/closedir/readdir)的使用方法;2. 目录位置记录的telldir和seekdir函数;3. 文件状态信息获取的stat/fstat/lstat函数;4. 通过实际代码示例演示了如何遍历目录、获取文件详细信息;5. 最后实现了一个模拟ls命令的程序,能够输出文件的类型、权限、所有者、大小和修改时间等信息。文章详细讲解了各函数参数、结构体定义和使用注意事项,为Linux系统编程中的目录和文件
2025-07-09 19:34:31
828
原创 C++ unordered_map 容器总结
基于实现。元素的存储顺序是,取决于哈希函数和哈希表的结构。插入、删除和查找操作的平均时间复杂度为,但在最坏情况下(如大量哈希冲突)可能退化到O(n)。键是,元素的存储和遍历顺序取决于哈希函数和哈希表的结构。如果需要按键值顺序遍历,需要额外排序。内存使用可能比std::map稍高,因为哈希表需要额外的空间来处理哈希冲突(如开放寻址法或链表法)。但可以通过调整负载因子(load factor)来优化内存使用。适用于需要频繁查找、插入和删除的场景,尤其是当数据量较大时。
2025-07-08 19:45:53
1407
原创 使用GDB调试程序方法
写程序难免会遇到 Bug,这时我们就需要 GDB 来对程序进行调试了。调试需要在编译的时候,加上一些调试相关的信息,也就是说,需要指定 -g 选项。如:其中-g选项表示生成调试信息。当你在编译程序时加上-g选项,gcc会在生成的包含额外的调试信息。这些调试信息主要是关于源代码和目标代码之间的映射关系等内容。例如,它会记录变量的名称、类型、位置,函数的入口点等信息。这些调试信息对于使用调试工具(如gdb)来调试程序非常重要。调试工具可以利用这些信息来帮助你查看变量的值、设置断点、单步执行等操作。
2025-06-24 20:54:12
988
原创 计算机史话:Unix&Linux的发展历史
早期的操作系统为批处理操作系统,输入设备只有卡片阅读机,输出设备只有打印机。程序员是在读卡纸上进行编程的,然后通过打孔机进行打孔,打孔表示 1,没打孔表示 0。这样的操作系统有个缺陷:如果计算机需要处理多个任务,那么后面的任务需要排队等待!1960年初,麻省理工 (MIT) 开发了划时代的兼容分时系统 CTSS (Compatible Time-Sharing System),它允许操作系统在多个任务之间来回切换。那时候计算资源非常宝贵,都是通过终端连接主机的形式来共享计算资源的。
2025-06-24 14:05:44
1246
原创 torch.nn 下的常用深度学习函数
Dropout 的主要用途是在训练过程中随机丢弃一部分神经元的输出,从而减少模型对训练数据的过拟合。常用于多分类问题,输入张量通常是模型的输出,目标张量是类别索引。将所有负值置为0,保留正值,是最常用的激活函数之一,能够加速训练过程。计算预测值与真实值之间的绝对值,它对异常值的敏感度较低,适用于回归问题。将输入值映射到(0,1)区间,常用于二分类问题的输出层。:模型的原始输出,形状为 (N,C),其中 N 是样本数,C 是类别数。:用于定义一个顺序模型,可以将多个层按顺序堆叠起来,简化模型的定义过程。
2025-05-10 21:19:56
1402
原创 Python torch.optim.lr_scheduler 常用学习率调度器使用方法
学习率(Learning Rate)是深度学习中一个关键的超参数,它决定了在优化算法(如梯度下降法)更新模型参数时,参数调整的幅度。简单来说,它控制着模型在训练过程中朝着最小化损失函数方向前进的步伐大小。假设我们使用简单的梯度下降法来更新模型的参数,对于损失函数,其更新规则可以表示为:其中,就是学习率。这个公式的意思是,在参数更新时,我们沿着损失函数梯度的反方向(因为梯度方向是函数增长最快的方向,我们要求最小值,所以取反方向)移动,移动的步长由学习率决定。学习率的重要性学习率过大。
2025-04-25 14:58:36
1779
原创 Python torchvision.transforms 下常用图像处理方法
是 PyTorch 用于处理图像数据的一个模块,提供了丰富的图像变换功能。
2025-04-24 21:30:23
1439
原创 Mixup数据增强方法总结
Mixup 通过其核心思想是具体来说,对于两个样本及其对应的独热编码标签,按照一定比例进行加权混合,从而得到一个新的样本和标签。
2025-04-23 14:42:18
3518
数据库实验2.rar
2020-02-09
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅