如何将Git仓库中的特定文件夹及其历史完整迁移到另一个仓库
@[toc] 实战指南:如何将Git仓库中的特定文件夹及其历史完整迁移到另一个仓库在软件项目的演进过程中,我们经常会遇到需要重构代码库的场景。一个常见的需求是:将一个庞大的单体仓库(Monorepo)中的某个模块或组件拆分出来,或者将一个项目中的公共部分提取到一个共享库中。这个过程中,最大的挑战莫过于如何在迁移文件的同时,完整地保留其宝贵的 Git 提交历史。 本文将通过一个真实场景,一步步教你如何使用 git filter-repo 和 git subtree 等强大工具,安全、高效地完成这一任务。 场景设定假设我们有两个本地仓库: 源仓库 (Source):位于 E:\CODE\fork,这是一个功能复杂的项目。 目标仓库 (Destination):位于 E:\CODE\test,我们希望将源仓库的一部分功能迁移到这里。 我们的目标是:从源仓库中,只提取 axis 和 UserSrc 这两个文件夹,并将它们相关的、完整的 Git 历史记录,合并到目标仓库中。 第一步:筛选和剥离历史(使用 git filter-repo)要从源仓库中精确地“剥离”出我们想要的文件夹历史...
将 Git 仓库所有文件移入子目录的正确姿势
@[toc] 从错误到精通:将 Git 仓库所有文件移入子目录的正确姿势1git mv (git ls-tree --name-only HEAD | Where-Object { $_ -ne 'light' }) .\light 在软件项目的生命周期中,重构是常有的事。一个常见的重构任务便是将项目根目录下的所有文件和文件夹移动到一个新的子目录中,例如 src、source 或 app。这个操作看似简单,但在 Git 中,如果想完美地保留所有文件的提交历史,就需要一点技巧。 本文将记录一次完整的探索过程,从最初的错误尝试,到分析问题根源,最终找到在 PowerShell 和 BAT 脚本中都行之有效的、能够保留 Git 历史的完美解决方案。 起始点:一个常见但错误的想法任何一个熟悉命令行的人,第一反应可能都是使用通配符 *: 123# 错误的做法!mkdir new_foldergit mv * new_folder/ 这很快就会失败,并提示一个类似“不能将目录移动到自身子目录中”的错误。原因是 Shell (命令行) 会将 ...
Linux 内核 `jiffies` 更新机制解析:周期性Tick模型和动态时钟
@[toc] Linux 内核 jiffies 更新机制解析:周期性Tick模型和动态时钟/无Tick模型的实现与行为 1. jiffies 更新的双重模型框架Linux内核对jiffies全局计数器的更新并非采用单一策略,而是根据中央处理器(CPU)的运行状态和系统配置,在两种截然不同的模型间进行切换。 1.1 周期性Tick模型 (Periodic Tick Model) 适用条件:此模型在CPU持续执行非空闲任务,或内核未完全开启CONFIG_NO_HZ_FULL等动态时钟配置时被激活。 工作机制:内核中存在一个周期性的时钟中断事件。该中断以一个由内核编译时配置的HZ值所决定的固定频率(例如250Hz)规律性地发生。在现代内核中,此中断通常由高精度定时器(hrtimer)模拟的tick_sched_timer来驱动。 jiffies更新行为:在每一次时钟中断的服务例程中,tick_periodic()函数都将被调用,其核心任务之一就是将全局变量jiffies_64的值原子性地增加1。在此模型下,jiffies的增长是线性的、可预测的。 其更新流程如下图所示:...
Linux 内核 API 设计哲学:`NULL` 指针语义的上下文依赖性分析
@[toc] Linux 内核 API 设计哲学:NULL 指针语义的上下文依赖性分析 摘要在操作系统内核这样的大型、复杂的软件系统中,对边界条件和异常输入的处理方式,深刻地反映了其核心设计哲学。NULL 指针作为一种常见的边界值,其处理策略并非一成不变。本文通过对 Linux 内核中两个不同子系统——内核线程(kthread)和高精度定时器(timer)——的处理方式进行比较分析,旨在阐明内核如何根据 API 契约、设计意图和运行时上下文,为 NULL 指针赋予截然不同的语义,并采取从“快速失败”到“静默忽略”的迥异处理策略。 1. 引言健壮的软件系统必须对其接口的输入进行有效性验证。在C语言环境中,函数指针参数的NULL检查是一种常见的防御性编程实践。然而,在Linux内核的设计中,并非所有函数指针在使用前都会进行显式的NULL检查。这种差异并非疏忽,而是基于深思熟虑的设计决策。本文选取 kthread_create() 的 threadfn 参数和 timer_setup() 的 function 参数作为研究对象,探讨其背后隐藏的设计原则。 2. 案例分析一:kthr...
Linux 内核 `kthread_stop` 完成量等待是如何被唤醒
@[toc] Linux 内核 kthread_stop 完成量等待是如何被唤醒 引言在Linux内核编程中,kthread_stop 是一个用于请求并同步等待内核线程(kthread)退出的标准函数。其接口定义清晰,但其内部的同步机制横跨了调度、内存管理和进程退出的多个核心子系统。调用 kthread_stop 的线程会因 wait_for_completion 调用而阻塞,直至目标线程彻底退出。本文旨在精确剖析并阐述 kthread_stop 的同步唤醒机制,揭示其依赖于对 task_struct->vfork_done 字段的重用,并通过标准的 mm_release 路径触发唤醒信号的实现细节。 一、 机制基础:set_kthread_struct 函数中的指针重用理解 kthread_stop 唤醒路径的前提,是对内核线程创建时的数据结构初始化进行分析。在线程创建过程中,set_kthread_struct 函数负责关联 task_struct 与 kthread 私有结构体,并在此过程中建立了一个决定性的链接。 set_kthread_struct 源码解析1...
Linux 内核中断与时间子系统深度解析:从硬件到`jiffies`的完整生命周期
@[toc] Linux 内核中断与时间子系统深度解析:从硬件到jiffies的完整生命周期 1. 引言Linux内核的稳定运行,高度依赖于其底层两大基石——中断处理框架与时间管理子系统。中断框架负责响应来自硬件的异步事件,而时间管理子系统则为整个内核提供统一的时间基准——jiffies全局节拍计数器。这两大系统并非独立运行,而是通过一套设计精良、层次分明的接口进行精密协作。在某些配置模式下,jiffies的每一次递增,都源于一个硬件定时器产生的物理中断。 本文旨在对这一协作过程进行一次完整的、端到端的深度剖析。我们将首先详细阐述jiffies的双重更新模型,然后分别深入其在动态时钟(NOHZ)和高精度定时器驱动下的实现路径。随后,文章将回溯到传统的低精度模式,分析硬件定时器如何被注册为系统节拍源,并追踪一个硬件中断从发生到最终触发通用tick处理的完整流程。最后,我们将对内核中断处理的完整生命周期进行梳理,揭示其从静态初始化到运行时触发的精妙设计。 2. jiffies 的双重更新模型Linux内核对jiffies的更新并非采用单一策略,而是根据CPU的运行状态和系统配置,...
Linux 内核调度、内存管理与并发的交汇点:`membarrier` 与 `finish_task_switch` 深度解析
@[toc] Linux 内核调度、内存管理与并发的交汇点:membarrier 与 finish_task_switch 深度解析 引言在现代多核处理器架构下,保证不同CPU核心之间的内存操作顺序和可见性,是操作系统内核必须解决的核心挑战之一。membarrier 系统调用为此而生,它为用户态程序提供了一种强制同步不同核心内存视图的机制。然而,在内核复杂的任务切换路径中,确保 membarrier 的语义被正确实现,揭示了 Linux 内核在性能优化与并发正确性之间精妙的权衡。本文将深入剖析在特定任务切换场景下,finish_task_switch 函数中一段看似不起眼的代码,如何巧妙地解决了因“懒惰TLB”(Lazy TLB)优化而引入的内存同步漏洞,并阐释其背后涉及的内存管理、任务调度与并发控制的联动机制。 一、 问题的根源:membarrier 与内核线程切换1.1 membarrier 系统调用的契约membarrier() 系统调用的核心使命是建立一道内存屏障。当一个线程修改了内存,并希望确保运行在其他CPU核心上的线程能够观察到这些修改时,便会调用 membar...
Linux内核ARM架构下`sys_call_table`的自动化生成机制剖析
@[toc] Linux内核ARM架构下sys_call_table的自动化生成机制剖析 1. 引言在Linux操作系统内核中,系统调用(System Call)构成了用户空间与内核空间交互的基础接口。为了高效地将用户空间传递的系统调用号(System Call Number, SCN)映射至内核中相应的服务例程,内核在内部维护了一个核心数据结构——系统调用表。对于ARM架构,此表定义为sys_call_table,其本质是一个函数指针数组。 维护这样一个包含数百个条目,且需兼容多种应用程序二进制接口(Application Binary Interface, ABI)的数组,是一项复杂且易错的任务。任何手动的编辑都可能引入调用号与函数指针不匹配、ABI兼容性层实现错误或表大小同步失败等严重问题。为规避此类风险,Linux内核采用了一套高度自动化的代码生成机制。本文旨在以严谨的技术视角,对ARM架构下sys_call_table从源定义文件到最终二进制镜像中符号的全过程,进行深入、详尽的剖析。 2. sys_call_table 自动化生成流程sys_call_table的构...
新线程创建和退出的异同点解析
@[toc] [linux][rtos]新线程创建和退出的异同点解析 1. 引言在现代多任务操作系统中,线程是调度的基本单位。当一个新线程被创建后,它并不会立即执行,而是处于就绪状态,等待操作系统的调度器(Scheduler)首次将CPU的控制权交给它。这个从“被调度”到“开始执行第一行有效代码”的过渡过程,并非一次简单的函数跳转,而是由一个精心设计的、位于内核深处的“启动入口”来完成的。这个入口点,我们称之为新线程的“第一步”。 本文旨在深入剖析两个极具代表性的操作系统——通用的宏内核Linux和嵌入式实时操作系统RT-Thread——它们各自是如何实现新线程的“第一步”的。我们将重点分析Linux ARM架构下的ret_from_fork汇编例程,以及RT-Thread中的rt_thread_startupC语言函数。通过对比这两种在不同层级、不同复杂度环境下实现的机制,本文将揭示操作系统在任务启动这一核心功能上共通的设计哲学与差异化的实现策略,为内核开发者和嵌入式系统工程师提供一个深入理解操作系统底层运作的独特视角。 2. 上下文的伪造:新线程首次执行的“前夜”无论是L...
深度解析优先级继承:从问题根源到Linux与RTOS实现
@[toc] 深度解析优先级继承:从问题根源到Linux与RTOS实现 引言在实时操作系统(RTOS)和具备实时能力的通用操作系统(如配置了PREEMPT_RT的Linux)中,任务调度的**可确定性(Determinism)**是至关重要的。这意味着高优先级的任务必须能够在其截止时间(Deadline)内得到响应和执行。为实现此目标,**优先级抢占(Priority Preemption)**是其核心调度策略。 然而,当多任务系统引入共享资源和互斥锁后,一个严重的问题可能出现——优先级反转(Priority Inversion)。它会破坏优先级抢占机制的正常运作,进而影响系统的可确定性。为了修正这一问题,操作系统引入了**优先级继承(Priority Inheritance, PI)**机制。 本文将首先明确区分优先级抢占与优先级反转,然后通过逻辑流程图展示优先级反转的发生过程,并阐述优先级继承是如何解决此问题的。随后,我们将附上Linux内核中实现此功能的rt_mutex_adjust_prio_chain函数完整源码,并对其执行流程进行详尽的分解说明。最后,本文将横向对...