从引导扇区到加载器:自制操作系统Boot阶段实战指南
1. 从引导扇区到加载器为什么不能一步到位很多人第一次接触自制操作系统都会有一个特别朴素的想法既然 BIOS 会把硬盘第一个扇区512 字节加载到内存里执行那我直接把整个操作系统塞进这 512 字节不就行了我当初也是这么想的直到我真正动手写的时候才发现512 字节连一个像样的屏幕输出函数都写不完整更别提什么内存管理、中断处理了。所以 Boot 阶段的核心任务其实不是运行操作系统而是把操作系统从硬盘搬进内存然后把控制权交出去。这个过程就像搬家引导扇区是那个先到新房子开门的人他手里只有一把钥匙和一张纸条纸条上写着真正的家具在楼下仓库的第三个柜子里他的工作就是找到仓库、把家具搬上来然后打电话告诉主人可以入住了。这一篇要聊的就是 Boot 的第二阶段——从 512 字节的引导扇区过渡到一个功能完整的加载器Loader。这个加载器要能干这些事读取硬盘上更多的扇区、把内核加载到指定内存地址、切换到保护模式、最后跳转到内核入口。听起来步骤不多但每一步都有坑而且这些坑往往不会报错只会让你的机器重启或者卡死排查起来非常痛苦。这篇文章适合已经写完第一阶段引导扇区、能打印出 Hello World 的朋友。如果你还没到这一步建议先把实模式下的屏幕输出和磁盘读取搞明白否则后面的内容会有点吃力。我会把每个环节的原理、代码结构、参数计算和踩坑经验都讲清楚尽量让你少走弯路。2. 整体设计思路为什么需要 Loader 这一层2.1 512 字节的硬约束与破局思路引导扇区的 512 字节限制是硬件层面的不是软件能绕过的。BIOS 读取硬盘第一个扇区到内存0x7C00处然后检查最后两个字节是不是0x55AA是的话就跳过去执行。整个过程就这么简单粗暴没有任何商量余地。那这 512 字节里能干什么我实测下来一个基本的屏幕输出函数大概要 30 到 50 字节一个磁盘读取函数用 BIOS 的int 0x13大概要 60 到 80 字节再加上一些初始化和错误处理留给业务逻辑的空间非常有限。你想在这点空间里实现文件系统解析、内存检测、保护模式切换基本不可能。所以业界的通用做法是引导扇区只负责把 Loader 从硬盘读进内存然后跳过去执行。Loader 本身不受 512 字节限制可以写得足够复杂。这个思路的好处是职责清晰——引导扇区是搬运工Loader 是包工头内核是住户。具体怎么读用 BIOS 中断int 0x13的AH0x02功能从硬盘读取指定数量的扇区到指定内存地址。这里有个关键点读取的目标地址不能覆盖当前正在执行的引导扇区代码否则你读到一半把自己覆盖了后面的代码就全乱了。我一般把 Loader 加载到0x1000或者0x8000这样的地址远离0x7C00。2.2 Loader 的职责边界划分Loader 要干哪些事这个边界得提前想清楚不然后面写内核的时候会反复回来改。我的经验是Loader 至少应该承担这几项职责加载内核从硬盘的固定位置比如第二个扇区开始读取内核镜像到内存。内核镜像可以是 raw 二进制也可以是简单的自定义格式看你后续怎么设计。获取关键硬件信息比如通过 BIOS 中断获取内存布局int 0x15, EAX0xE820这些信息在进入保护模式后就拿不到了必须提前存好。切换到保护模式设置 GDT、开启 A20 地址线、设置 CR0 寄存器的 PE 位。这一步是 32 位操作系统的门槛不过也得过。跳转到内核入口把之前收集的信息内存布局、启动参数等以约定好的格式传给内核然后跳过去。为什么不把这些事都放到内核里做因为有些操作比如 BIOS 中断只能在实模式下执行而内核通常运行在保护模式甚至长模式。你不可能在 32 位代码里调用 16 位的 BIOS 中断所以这些脏活必须在 Loader 阶段完成。2.3 内存布局的规划原则在动手写代码之前先把内存布局画出来这个习惯能帮你省下大量调试时间。我一般会规划成这样内存地址范围用途说明0x00000 - 0x003FF中断向量表BIOS 使用不要动0x00400 - 0x004FFBIOS 数据区存放硬件信息可读取0x00500 - 0x07BFF可用区域可以放临时数据0x07C00 - 0x07DFF引导扇区当前执行的代码0x07E00 - 0x0FFFF可用区域栈可以放这里0x10000 - 0x7FFFFLoader 和内核主要工作区域0x80000 以上扩展内存需要 BIOS 检测才能用这个布局不是固定的你可以根据实际情况调整。关键是不要让自己的代码或数据覆盖了正在使用的中断向量表、BIOS 数据区或者栈空间。我踩过一次坑把栈设置在0x7C00附近结果引导扇区代码一执行就把栈给覆盖了机器直接死机查了半天才发现是栈的问题。3. 核心细节解析磁盘读取与地址计算3.1 用 int 0x13 读取硬盘的正确姿势BIOS 的int 0x13是实模式下读硬盘的唯一选择但它的参数设置有点绕尤其是 CHS柱面-磁头-扇区寻址方式跟我们现在习惯的 LBA逻辑块地址完全不一样。先看参数AH 0x02表示读取扇区AL要读取的扇区数量注意不能跨磁道CH柱面号低 8 位CL扇区号bit 0-5加上柱面号高 2 位bit 6-7DH磁头号DL驱动器号硬盘一般是0x80ES:BX数据读取到内存的哪个地址这里最容易出错的是CL寄存器的结构。扇区号从 1 开始计数占 6 位柱面号的高 2 位放在CL的 bit 6-7。也就是说如果你要读柱面 0、磁头 0、扇区 2那么CL的值就是0x02如果要读柱面 256、扇区 1柱面号 256 的二进制是1 0000 0000高 2 位是01低 8 位是0x00所以CH 0x00CL 0x4101左移 6 位加上扇区号 1。我写了一个简单的转换函数把 LBA 地址转成 CHS 参数这样调用的时候就不用每次都手算; LBA 转 CHS ; 输入: EAX LBA 地址 ; 输出: CH 柱面号低8位, CL 扇区号柱面高2位, DH 磁头号 lba_to_chs: xor edx, edx mov ecx, 63 ; 每磁道 63 个扇区 div ecx ; EAX / 63, 商在 EAX, 余数在 EDX inc edx ; 扇区号从 1 开始 mov cl, dl ; CL 扇区号 xor edx, edx mov ecx, 16 ; 每柱面 16 个磁头 div ecx ; EAX / 16, 商是柱面号, 余数是磁头号 mov ch, al ; CH 柱面号低 8 位 mov dh, dl ; DH 磁头号 ; 柱面号高 2 位放到 CL 的 bit 6-7 shr eax, 8 and al, 0x03 shl al, 6 or cl, al ret这段代码假设硬盘的几何结构是每磁道 63 个扇区、每柱面 16 个磁头这是历史遗留的标准值现代硬盘虽然物理结构不同但 BIOS 通常会模拟这个几何结构所以用起来没问题。注意int 0x13读取的扇区数不能跨磁道。如果你要读 20 个扇区而当前磁道只剩 10 个扇区就得分成两次读。我一般保守一点每次最多读 18 个扇区避免边界问题。3.2 读取失败的重试机制磁盘读取不是 100% 可靠的尤其是从真实硬件启动的时候偶尔会失败。BIOS 在读取失败时会设置进位标志CF并在AH中返回错误码。如果不处理程序就会继续执行垃圾数据结果不可预测。我的做法是加重试机制最多重试 3 次每次失败后重置磁盘控制器AH0x00然后再试。如果 3 次都失败就打印错误信息并停机。这个逻辑虽然简单但能解决大部分偶发性的读取失败。read_sectors: mov di, 3 ; 重试次数 .retry: pusha mov ah, 0x02 ; ... 设置其他参数 ... int 0x13 jnc .done ; 成功则跳转 ; 失败重置磁盘 mov ah, 0x00 int 0x13 popa dec di jnz .retry ; 三次都失败报错 mov si, msg_disk_error call print_string jmp $ .done: popa ret这里有个细节int 0x13会修改一些寄存器的值所以在重试之前要先把寄存器恢复用pusha/popa否则第二次重试的参数就乱了。3.3 内核镜像的格式约定Loader 怎么知道内核有多大、要加载到哪个地址这需要一个约定。最简单的做法是内核镜像的前几个字节存放元信息比如加载地址、入口地址、镜像大小Loader 先读第一个扇区解析元信息然后再读剩余部分。我设计了一个简单的头部结构占 16 个字节偏移大小含义0x004 字节魔数用于校验比如 0x4B524E4C0x044 字节加载地址0x084 字节入口地址0x0C4 字节镜像大小字节Loader 先读内核的第一个扇区到临时缓冲区检查魔数对不对然后根据镜像大小计算还需要读多少个扇区最后把整个镜像读到加载地址。这个方案的好处是内核的位置和大小可以灵活调整不用每次改 Loader 的代码。提示魔数的作用是防止 Loader 读到了错误的数据比如硬盘上根本没有内核。如果魔数不匹配就打印错误信息而不是盲目跳转过去执行。4. 实操过程从实模式到保护模式的完整实现4.1 引导扇区如何加载 Loader引导扇区的代码要尽量精简它的任务就是设置栈、读取 Loader、跳过去执行。我一般把 Loader 放在硬盘的第二个扇区开始读 16 个扇区8KB加载到内存0x1000处。[org 0x7C00] [bits 16] start: ; 设置栈 xor ax, ax mov ss, ax mov sp, 0x7C00 ; 栈向下增长不会覆盖引导扇区 ; 读取 Loader 到 0x1000 mov ax, 0x1000 mov es, ax xor bx, bx ; ES:BX 0x1000:0x0000 mov ah, 0x02 ; 读取功能 mov al, 16 ; 读 16 个扇区 mov ch, 0 ; 柱面 0 mov cl, 2 ; 从第 2 个扇区开始 mov dh, 0 ; 磁头 0 mov dl, 0x80 ; 硬盘 0 int 0x13 jc disk_error ; 跳转到 Loader jmp 0x1000:0x0000 disk_error: mov si, msg_error call print_string jmp $ print_string: ; ... 省略具体实现 ... ret msg_error db Disk read error!, 0 times 510-($-$$) db 0 dw 0xAA55这段代码里栈设置在0x7C00向下增长所以栈的数据会落在0x7C00以下不会覆盖引导扇区本身。ES:BX设置为0x1000:0x0000也就是物理地址0x10000这是 Loader 的加载位置。4.2 Loader 的第一件事重新设置段寄存器Loader 被加载到0x10000后第一件事是重新设置段寄存器因为引导扇区跳过来的时候CS可能还是0x0000但DS、ES可能还是之前的值。如果不重新设置后面访问数据的时候就会出错。[org 0x0000] ; 注意这里 org 是 0因为段基址是 0x1000 [bits 16] loader_start: ; 重新设置段寄存器 mov ax, cs mov ds, ax mov es, ax mov ss, ax mov sp, 0xFFFF ; 栈设置在段内偏移 0xFFFF 处 ; 打印一条消息确认 Loader 运行了 mov si, msg_loader call print_string ; ...这里有个容易混淆的地方org的值取决于你用什么段基址来执行代码。如果跳转的时候用的是jmp 0x1000:0x0000那么CS 0x1000代码在段内的偏移从 0 开始所以org 0x0000。如果你用jmp 0x0000:0x1000那CS 0x0000偏移是0x1000org就得写0x1000。两种方式都能用但一定要对应上否则所有标签的地址都会算错。4.3 获取内存布局E820 内存检测进入保护模式之前必须知道物理内存的布局否则内核没法管理内存。BIOS 提供了int 0x15, EAX0xE820功能来获取内存映射它会返回一个结构数组每个结构描述一段内存的基地址、长度和类型。调用方式是这样的; 设置 E820 调用参数 mov eax, 0xE820 mov ebx, 0 ; 第一次调用时 EBX 0 mov ecx, 24 ; 缓冲区大小通常 24 字节 mov edx, 0x534D4150 ; 魔数 SMAP mov di, buffer ; ES:DI 指向缓冲区 int 0x15返回后EAX应该是0x534D4150表示成功EBX是下一个结构的索引如果为 0 表示结束ECX是实际写入的字节数。每个结构长这样偏移大小含义0x008 字节基地址0x088 字节长度0x104 字节类型1可用2保留3ACPI4NVS0x144 字节扩展属性通常为 0我一般会把结果存到一个数组里最多存 32 个条目然后在跳转到内核之前把这个数组的地址传给内核。这里要注意int 0x15会修改EBX和ECX所以每次循环都要重新设置ECX和EDX。注意有些老机器不支持 E820会返回错误。这时候可以退回到 E801 或者 88 号中断但那些方法获取的信息不完整。如果目标机器比较新直接用 E820 就行。4.4 开启 A20 地址线A20 地址线是历史遗留问题。早期的 8086 只有 20 根地址线能访问 1MB 内存。后来的 CPU 地址线更多但为了兼容默认第 21 根地址线A20是关闭的导致访问超过 1MB 的地址时会回绕到 0。进入保护模式之前必须打开 A20否则访问高地址内存会出错。打开 A20 有几种方法我一般用键盘控制器的方法因为它兼容性最好enable_a20: ; 禁用键盘 call a20_wait_input mov al, 0xAD out 0x64, al ; 读取输出端口 call a20_wait_input mov al, 0xD0 out 0x64, al call a20_wait_output in al, 0x60 push eax ; 设置 A20 位 call a20_wait_input mov al, 0xD1 out 0x64, al call a20_wait_input pop eax or al, 2 out 0x60, al ; 启用键盘 call a20_wait_input mov al, 0xAE out 0x64, al call a20_wait_input ret a20_wait_input: in al, 0x64 test al, 2 jnz a20_wait_input ret a20_wait_output: in al, 0x64 test al, 1 jz a20_wait_output ret这段代码看起来有点长但逻辑很清晰通过向键盘控制器发送命令读取输出端口的值把 bit 1 置 1再写回去。a20_wait_input和a20_wait_output是等待键盘控制器就绪的辅助函数不加这两个等待在某些机器上会失败。4.5 设置 GDT 并进入保护模式GDT全局描述符表是保护模式的基础它定义了内存段的基地址、长度和权限。进入保护模式之前必须设置好 GDT并用lgdt指令加载。我一般定义三个段描述符空描述符必须、代码段、数据段。代码段和数据段的基地址都设为 0长度设为 4GB权限设为可读可写可执行。这样简化了内存访问不用考虑分段的问题。gdt_start: ; 空描述符 dd 0x00000000 dd 0x00000000 ; 代码段基址 0长度 4GB可执行可读 dw 0xFFFF ; 段长度低 16 位 dw 0x0000 ; 段基址低 16 位 db 0x00 ; 段基址中间 8 位 db 10011010b ; 访问权限存在、特权级 0、代码段、可读 db 11001111b ; 标志4KB 粒度、32 位、段长度高 4 位 db 0x00 ; 段基址高 8 位 ; 数据段基址 0长度 4GB可读写 dw 0xFFFF dw 0x0000 db 0x00 db 10010010b ; 访问权限存在、特权级 0、数据段、可写 db 11001111b db 0x00 gdt_end: gdt_descriptor: dw gdt_end - gdt_start - 1 ; GDT 长度 dd gdt_start ; GDT 基地址加载 GDT 并进入保护模式的代码enter_protected_mode: cli ; 关闭中断 lgdt [gdt_descriptor] ; 设置 CR0 的 PE 位 mov eax, cr0 or eax, 1 mov cr0, eax ; 远跳转刷新流水线 jmp 0x08:protected_mode_start [bits 32] protected_mode_start: ; 设置数据段寄存器 mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax mov esp, 0x90000 ; 设置栈指针 ; 跳转到内核 jmp 0x08:kernel_entry这里的关键是jmp 0x08:protected_mode_start0x08是代码段在 GDT 中的偏移第一个描述符是空描述符占 8 字节所以代码段从偏移 8 开始。这个远跳转不仅跳转了地址还会把CS设置为0x08同时刷新 CPU 流水线确保后面的代码以 32 位模式执行。注意进入保护模式后原来的实模式中断向量表就不能用了。如果在保护模式下需要处理中断得重新设置 IDT中断描述符表。不过在 Loader 阶段我一般直接关中断cli等内核初始化好了再开。5. 常见问题与排查技巧实录5.1 机器不断重启或卡死这是最常见的问题原因通常有几个栈设置错了、读取的扇区数太多跨了磁道、跳转地址不对、GDT 描述符写错了。排查的时候我一般用二分法先在引导扇区里打印一条消息确认引导扇区执行了然后在 Loader 开头打印一条消息确认 Loader 加载了再在进入保护模式之前打印一条消息确认前面的步骤都成功了。如果打印到某一步就不输出了问题就出在那一步和上一步之间。比如引导扇区打印了Loader 的消息没打印那问题就在磁盘读取或者跳转上。5.2 保护模式跳转后死机进入保护模式后死机最常见的原因是 GDT 描述符写错了。检查这几个点段长度和基地址的拼接是否正确、访问权限字节的 bit 4 是否设置为 1表示代码段或数据段而不是系统段、粒度位是否设置正确。还有一个容易忽略的点进入保护模式后DS、ES等段寄存器的值还是实模式下的值必须重新设置。如果不设置访问数据时用的还是实模式的段基址结果完全不对。5.3 读取的内核数据不对如果内核加载后运行异常先检查读取的数据对不对。我一般会在 Loader 里把读到的内核头部打印出来看看魔数、加载地址、入口地址是不是预期的值。如果魔数不对说明读的位置错了如果魔数对但其他字段不对说明读取的偏移或者字节序有问题。还有一个坑int 0x13读取时AL不能为 0。有些 BIOS 把AL0解释为读取 256 个扇区有些则认为是读取 0 个扇区。我一般至少读 1 个扇区避免歧义。5.4 常见问题速查表现象可能原因排查方法引导扇区不执行最后两字节不是 0x55AA用十六进制工具查看镜像最后两字节读盘失败CHS 参数错误或跨磁道打印 CHS 参数确认扇区号从 1 开始Loader 不执行跳转地址错误确认org和跳转指令的段:偏移一致保护模式死机GDT 描述符错误逐字节检查 GDT确认权限字节内核不执行入口地址错误打印内核头部确认入口地址内存检测失败BIOS 不支持 E820检查EAX返回值考虑降级方案5.5 几个实用的调试技巧第一个技巧是用屏幕输出代替调试器。在实模式下直接写显存0xB8000就能输出字符不需要任何库。我一般写一个print_hex函数把寄存器的值以十六进制打印出来这样能直观地看到数据对不对。第二个技巧是用 QEMU 的调试功能。QEMU 支持-d参数输出 CPU 状态比如-d int可以打印中断信息-d cpu可以打印寄存器状态。配合-no-reboot参数机器出错时不会重启方便你查看最后的错误状态。第三个技巧是在关键位置插入jmp $。如果怀疑某段代码有问题就在它后面加一个死循环看看程序能不能执行到那里。这个方法虽然笨但非常有效。6. 从 Loader 到内核的交接细节6.1 传递参数的约定Loader 收集到的信息内存布局、启动设备号等需要传给内核。传递方式有两种一种是通过寄存器传递另一种是把信息放在内存的固定位置内核自己去读。我一般用后者因为寄存器的数量有限而且保护模式切换后寄存器的值可能会变。具体做法是在内存的某个固定地址比如0x500放一个结构体里面包含内存布局数组的地址、数组长度、启动设备号等。Loader 在跳转之前把这个结构体填好内核启动后直接从这个地址读取。; 在 0x500 处存放启动信息 mov dword [0x500], memory_map_addr ; 内存布局数组地址 mov dword [0x504], memory_map_count ; 数组长度 mov byte [0x508], dl ; 启动设备号这个约定要提前和内核开发者或者你自己商量好不然后面改起来很麻烦。6.2 跳转前的最后检查在跳转到内核之前我一般会做几项检查确认内核头部已经正确解析、确认内存布局数组已经填好、确认 GDT 已经加载、确认 A20 已经打开。这些检查虽然不能保证万无一失但能提前发现大部分问题。还有一点跳转之前要关中断。保护模式下的中断处理还没设置好如果这时候来了中断CPU 会去查 IDT但 IDT 还没设置结果就是三重故障Triple Fault机器直接重启。所以cli指令一定要加。6.3 内核入口的准备工作内核入口的第一件事是重新设置栈。Loader 设置的栈可能在内核看来不合适比如位置太低了内核一般会用自己的栈。我通常在内核的 BSS 段里预留一块栈空间入口代码先把ESP指向这块空间的顶部然后再调用其他函数。另外内核入口还要重新加载 GDT。虽然 Loader 已经加载了一个 GDT但内核可能有自己的 GDT包含更多的段描述符比如用户态代码段和数据段。重新加载 GDT 后段寄存器的值也要跟着更新。7. 我个人在实际操作中的几点体会写 Boot 这一块最大的感受就是细节决定成败。一个 bit 写错了可能就是几个小时的排查。我踩过最坑的一次是 GDT 的粒度位忘了设置结果段长度被解释成字节而不是 4KB 页访问稍微高一点的地址就越界了机器直接重启。后来养成了习惯每写一个描述符都对照手册逐位检查一遍。另一个体会是不要过早优化。一开始我想把 Loader 写得特别精简结果代码可读性很差出了问题根本查不出来。后来改成先写对再写好代码清晰了调试效率反而更高。Boot 阶段的代码量不大多占几百字节无所谓关键是逻辑要清楚。还有就是多准备几台测试环境。QEMU 很方便但有些问题只有在真实硬件上才会出现比如磁盘读取的时序问题。我一般会在 QEMU 上开发然后定期在真实机器上测试确保兼容性。最后分享一个小技巧把 Boot 阶段的每个步骤都编上号打印到屏幕上。比如 Stage 1: Boot sector loaded、Stage 2: Loader loaded、Stage 3: Memory detected、Stage 4: Protected mode entered。这样一旦卡住看最后打印的编号就知道问题出在哪一步比盲目猜测高效得多。这个习惯我从写 Boot 一直保留到写内核算是整个开发过程中最实用的经验之一。

相关新闻

存储型XSS后端防御:基于注解与Filter的全量清洗方案

存储型XSS后端防御:基于注解与Filter的全量清洗方案

先说一个我前阵子遇到的真实案例。我们某个管理后台的“个人备注”功能被人塞了一行<script>alert(document.cookie)</script>&#xff0c;当时没有造成实际损失&#xff0c;但这段代码在整个查询页面回显&#xff0c;同事一打开列表&#xff0c;浏览器直接弹窗。查…

2026/10/19 4:58:06 阅读更多 →
提示工程与Agentic AI实践:医疗随访效率翻倍的落地复盘

提示工程与Agentic AI实践:医疗随访效率翻倍的落地复盘

三个月前&#xff0c;我还真没想过&#xff0c;自己天天琢磨的提示工程和Agentic AI&#xff0c;最后会扎进医疗随访这个领域&#xff0c;而且效果会这么直接。项目结束时&#xff0c;随访中心的外呼效率翻了两倍多&#xff0c;不是吹出来的两倍&#xff0c;是拿后台数据和排班…

2026/10/19 4:58:06 阅读更多 →
CTF文件管理器安全攻防:从路径遍历到完整利用链

CTF文件管理器安全攻防:从路径遍历到完整利用链

1. 从一道经典题目看文件管理器的安全设计盲区"文件管理器"这个词&#xff0c;做Web安全的人看到它&#xff0c;脑子里第一反应大概率不是那种桌面端的资源管理器&#xff0c;而是一个跑在浏览器里的、能上传、能查看、能删除文件的小型Web应用。这类应用在各类CTF比…

2026/10/19 4:58:06 阅读更多 →

最新新闻

前沿日报怎么做:从信息过载到高效筛选的完整指南

前沿日报怎么做:从信息过载到高效筛选的完整指南

1. 一份“前沿日报”到底在解决什么问题每天早上打开预印本平台&#xff0c;新论文像潮水一样涌进来&#xff0c;光是某个热门方向一天就能挂出几十上百篇。做研究的人最怕的不是没东西看&#xff0c;而是东西太多、太杂&#xff0c;看不过来&#xff0c;还容易漏掉真正重要的那…

2026/10/19 5:41:27 阅读更多 →
AI Agent桌面自动化:从对话框脚本到自主工作流的范式升级

AI Agent桌面自动化:从对话框脚本到自主工作流的范式升级

1. 为什么“走出对话框”是桌面自动化真正的分水岭“AI Agent赋能桌面自动化”这个说法最近在技术圈里被反复提起&#xff0c;但很多人第一次看到时&#xff0c;下意识反应是&#xff1a;“不就是用大模型写个Python脚本调用pyautogui吗&#xff1f;”——这恰恰踩中了当前绝大…

2026/10/19 5:41:27 阅读更多 →
局域网时间同步实战:NTP/chrony服务端与客户端配置及避坑指南

局域网时间同步实战:NTP/chrony服务端与客户端配置及避坑指南

简介&#xff1a;针对局域网设备时间不一致造成的日志错乱、数据一致性受损等问题&#xff0c;开发者提供了一套由服务器端与客户端组成的自定义时间同步方案。服务器端负责对外提供精确时间&#xff0c;客户端依据简单协议向指定服务器发送时间请求&#xff0c;并自动校准本地…

2026/10/19 5:41:27 阅读更多 →
Linux 0.11 内核实验指南:从引导扇区到系统调用的系统能力修炼

Linux 0.11 内核实验指南:从引导扇区到系统调用的系统能力修炼

简介&#xff1a;哈工大操作系统实验&#xff08;李治军&#xff09;完整资料包&#xff0c;面向计算机专业学生与操作系统自学者&#xff0c;通过真实内核代码与实验任务帮助理解进程管理、内存管理、文件系统、设备与调度算法等核心机制。包内245个文件&#xff0c;以C源码、…

2026/10/19 5:41:27 阅读更多 →
FLUX.2、Seedream、Z-image等五大图像生成模型选型指南

FLUX.2、Seedream、Z-image等五大图像生成模型选型指南

1. 当我们在聊图像生成模型时&#xff0c;到底在聊什么过去一年里&#xff0c;我身边做设计、做电商、做自媒体的朋友几乎都在问同一个问题&#xff1a;现在这些图像生成模型名字一个比一个陌生&#xff0c;FLUX.2、Seedream、Z-image、Qwen-Image、GLM-Image&#xff0c;到底哪…

2026/10/19 5:41:27 阅读更多 →
SSTI服务端模板注入实战:Jinja2漏洞原理、绕过与防御

SSTI服务端模板注入实战:Jinja2漏洞原理、绕过与防御

1. 漏洞本质与攻击面梳理1.1 模板引擎为什么成了攻击目标SSTI&#xff08;Server-Side Template Injection&#xff0c;服务端模板注入&#xff09;这个漏洞&#xff0c;我第一次真正意识到它的危害&#xff0c;是在一次授权渗透测试中遇到一个用Flask写的内部管理系统。那个系…

2026/10/19 5:40:26 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介&#xff1a;本资源为电源技术方向的学术研究文档&#xff0c;聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略&#xff0c;面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址&#xff1a; https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集&#xff0c;共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →