嵌入式Linux驱动源码解析:从字符设备到设备树与中断实战
简介一份面向嵌入式入门与进阶读者的华清远见培训驱动源码集合围绕Linux字符设备、块设备和网络设备展开覆盖设备驱动模型、file_operations结构、设备树、中断处理、DMA传输等核心知识适合正在系统学习驱动开发或准备嵌入式项目实践的读者对照源码理解内核运作。压缩包共286个文件其中98个C源文件与23个readme构成主要学习主线36个Makefile用于编译9个ko内核模块可直接加载观察效果30个cmd脚本辅助实验24个vsd原理图补充硬件连接背景整体仅4.97MB便于快速下载并在测试环境使用。资料整理自华清远见培训实战项目收录dm9000网卡驱动、sbull块设备驱动、fs210按键驱动等典型示例代码中体现I/O读写、设备注册注销、中断服务、电源管理、DMA传输及GPIO/SPI/I2C等接口编程要点。已有576人学习下载对希望借助真实驱动代码提升实践能力的读者具有较强参考价值。1. 这套驱动源码值得静下心啃一遍嵌入式Linux驱动的入门搭子很多做嵌入式的人C语言和单片机玩得挺溜一碰到Linux驱动就蔫了。原因倒不复杂驱动不是“写逻辑”而是“跟内核对话”缺了一份能跑、能拆、能对比的完整源码光看书很容易卡在概念上。这套培训用的驱动源码就是一份罕见的完整嵌入书——它不是东拼西揍的零散例程而是把字符设备、平台设备、设备树、中断、并发控制串起来的一套资料。适合刚放下单片机、准备往Linux方向走的开发者也适合写应用写了几年、想补驱动短板的工程师。它的价值在于所有机制都落在可编译、可加载的代码里跑一遍比看十遍书管用。2. 源码目录与驱动框架字符设备、平台设备、设备树三种套路怎么选2.1 源码目录怎么读先看入口 Makefile 还是先看 Kconfig拿到这套驱动源码第一反应肯定是打开文件夹挨个看.c文件这个习惯得改。源码通常有几十个文件没有讲解文档时最靠谱的入口是根目录的Makefile。Makefile里藏着三个关键信息编译目标、内核源码路径、交叉编译前缀。看懂这三行整套源码的工程结构就清楚了一半。一个典型的驱动模块Makefile长这样# 生成的目标模块名和组成源文件 obj-m : led_drv.o led_drv-objs : led_core.o led_platform.o # 内核源码树路径和架构 KERNELDIR : /home/user/linux-kernel ARCH : arm CROSS_COMPILE : arm-linux-gnueabihf- all: $(MAKE) -C $(KERNELDIR) M$(PWD) ARCH$(ARCH) CROSS_COMPILE$(CROSS_COMPILE) modules clean: $(MAKE) -C $(KERNELDIR) M$(PWD) ARCH$(ARCH) CROSS_COMPILE$(CROSS_COMPILE) cleanobj-m告诉内核构建系统把哪些源文件编成模块led_drv-objs把多个源文件合并成一个模块这个在源码里很常见因为培训例程往往把一个功能拆成多个文件方便单独讲。KERNELDIR指向内核源码不是指向开发板厂家的BSP包而是你要在内核源码目录里完成模块编译。ARCH和CROSS_COMPILE缺一不可前者指定ARM架构后者指定编译器前缀编译时make会用它拼出arm-linux-gnueabihf-gcc。很多新人直接把x86上的内核源码路径填进来编出的模块加载就报错这点后面避坑章节会细说。2.2 字符设备驱动骨架从 module_init 到 file_operations这套资源里数量最大的就是字符设备驱动涵盖LED、按键、ADC、PWM这类外设。字符设备的套路非常固定注册设备号、初始化cdev、实现file_operations、把操作接口挂进内核。源码里的核心结构基本是这个样子#include linux/module.h #include linux/fs.h #include linux/cdev.h #include linux/device.h #define DEVICE_NAME demo_dev static int demo_major 0; static struct cdev demo_cdev; static struct class *demo_class; static int demo_open(struct inode *inode, struct file *filp) { printk(KERN_INFO demo: open called\n); return 0; } static ssize_t demo_read(struct file *filp, char __user *buf, size_t len, loff_t *off) { /* 拷贝数据到用户空间的典型写法 */ if (copy_to_user(buf, hello\n, 6)) return -EFAULT; return 6; } static const struct file_operations demo_fops { .owner THIS_MODULE, .open demo_open, .read demo_read, }; static int __init demo_init(void) { dev_t devid; if (demo_major) { devid MKDEV(demo_major, 0); register_chrdev_region(devid, 1, DEVICE_NAME); } else { alloc_chrdev_region(devid, 0, 1, DEVICE_NAME); demo_major MAJOR(devid); } cdev_init(demo_cdev, demo_fops); cdev_add(demo_cdev, devid, 1); demo_class class_create(THIS_MODULE, demo_class); device_create(demo_class, NULL, devid, NULL, DEVICE_NAME); return 0; } static void __exit demo_exit(void) { dev_t devid MKDEV(demo_major, 0); device_destroy(demo_class, devid); class_destroy(demo_class); cdev_del(demo_cdev); unregister_chrdev_region(devid, 1); } module_init(demo_init); module_exit(demo_exit); MODULE_LICENSE(GPL);这段代码几乎覆盖了字符设备驱动的全部知识点。alloc_chrdev_region是动态分配主设备号避免手动指定主设备号时和已有设备冲突cdev_add之后内核才真正承认这个设备存在应用程序才能通过设备节点访问。class_create和device_create是配套动作前者在/sys下创建类后者负责在/dev下自动生成节点没有这两行insmod成功了也看不到设备文件。注意copy_to_user不能用memcpy替代因为用户态指针可能还没映射到内核地址空间这是驱动和普通C代码最大的区别之一。源码里这类驱动很好认只要看到file_operations结构体且里面的read/write直接对硬件寄存器操作就是典型的字符设备驱动。学习时先找一个只有open/read的例程把init和exit流程背下来再去看带硬件操作的版本会顺很多。2.3 平台设备与设备树驱动与硬件描述如何解耦这套资料里另一大类是平台设备驱动这类驱动出现在SoC内部外设场景比如串口控制器、I2C控制器、GPIO控制器。它和字符驱动的最大区别是驱动不自己找硬件地址而是等待内核把硬件信息“喂”过来。硬件信息在设备树里描述驱动通过compatible字段和设备树节点匹配。设备树里通常会有一段这样的描述led: led12000000 { compatible vendor,led; reg 0x12000000 0x1000; interrupts GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH; };驱动侧对应的匹配表写法是static const struct of_device_id led_of_match[] { { .compatible vendor,led }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, led_of_match); static int led_probe(struct platform_device *pdev) { struct resource *res; void __iomem *base; res platform_get_resource(pdev, IORESOURCE_MEM, 0); base devm_ioremap(pdev-dev, res-start, resource_size(res)); /* 之后用base操作寄存器 */ return 0; } static struct platform_driver led_driver { .probe led_probe, .driver { .name led, .of_match_table led_of_match, }, }; module_platform_driver(led_driver);这里platform_get_resource从设备树取寄存器地址和中断号devm_ioremap把物理地址映射为内核虚拟地址devm_前缀的好处是资源自动管理probe失败或驱动卸载时内核帮忙释放不用手动ioremap和iounmap对对齐。module_platform_driver是一个封装宏展开后就是module_init加module_exit减少样板代码。源码里平台设备驱动和字符设备驱动往往混在一起判断方法是看probe函数是否存在。有probe的说明硬件资源和驱动分离属于现代推荐的写法直接用固定地址ioremap的多半是教学为了简化而保留的老式写法。学习时建议优先看probe版本因为实际项目里设备树已经普及老式写法除了维护老平台基本用不上。3. 把驱动跑起来交叉编译、内核树准备与开发板部署3.1 交叉编译工具链版本错了后面全白搭源码在手第一件事不是读代码而是先把编译环境理清楚。这套驱动源码面向ARM开发板必须在x86主机上用交叉编译器构建。我说的“版本错了全白搭”不是夸张——编译器版本和内核编译时用的版本差异过大编出来的模块加载时会直接报version magic不匹配连insmod都过不去。交叉编译环境最少满足三个条件编译器支持目标架构、内核源码树和目标板运行内核版本一致、编译模块时ARCH和CROSS_COMPILE变量正确。通常培训机构会随资料附带工具链路径或者提示用arm-linux-gnueabihf-系列但如果资料里没写优先从开发板厂商的BSP里找工具链因为厂商会拿同一套工具链去编内核和模块兼容性最有保障。配置环境变量时我习惯把工具链路径写进~/.bashrcexport PATH$PATH:/opt/arm-toolchain/bin export ARCHarm export CROSS_COMPILEarm-linux-gnueabihf-ARCHarm不能省否则内核构建系统会按x86处理头文件路径、配置项全错。CROSS_COMPILE是前缀make在编译时会自动补全成arm-linux-gnueabihf-gcc、arm-linux-gnueabihf-ld这些命令。这两个变量放~/.bashrc里只对当前用户生效不影响系统其他项目比每次make时手动敲要稳。3.2 内核树的两种使用方式全量编译 vs 模块编译交叉编译驱动模块前需要先有一套和开发板运行内核对应的内核源码并且已经完成了基本配置。所谓“对应”包含两层意思版本号一致比如都是4.19.x配置项接近至少内核源码里的Module version magic要和目标板一致。实际操作中常见两种路径。第一种是整套内核源码先在目标板运行的内核配置基础上跑一遍全量编译之后再用同一套源码编模块第二种是只把内核源码解压出来用厂商提供的config文件生成Module.symvers然后直接编模块不做完整内核镜像。第一种最稳缺点是全量编译一次要二三十分钟第二种快但自己改过内核配置后容易出问题。编译模块的命令套路在Makefile里已经写好手动执行时是这样的make -C /path/to/kernel M/path/to/led_drv ARCHarm CROSS_COMPILEarm-linux-gnueabihf- modules-C指定内核源码目录M指定驱动源码目录两者必须写绝对路径。编完会在驱动源码目录生成.ko文件。注意这一步不会编译整个内核只编译模块所以速度很快几秒到十几秒。如果报缺少Module.symvers或vmlinux等文件说明内核源码没有先完成配置需要先回到内核源码目录执行make modules_prepare。3.3 insmod 之后的事加载、卸载与 dmesg 日志定位编译出.ko之后把它复制到开发板NFS、U盘、adb push都可以接下来就是加载和验证。基本命令就三条insmod、rmmod、dmesg。insmod led_drv.ko lsmod | grep led rmmod led_drv dmesg | tail -20很多新手习惯加载后直接找/dev下的节点找不到就以为驱动有问题。实际上字符设备驱动如果用了class_create和device_create节点会自动出现如果源码里只有register_chrdev_region和cdev_add没有device_create那就必须在加载后手动创建节点cat /proc/devices | grep led mknod /dev/led_drv c 240 0/proc/devices里能看到设备号和设备名mknod的c表示字符设备240和0就是主设备号和次设备号。如果每次重启都要手动mknod说明驱动代码少了设备创建部分这在老式教学源码里很常见不是板子问题。insmod和modprobe的区别也值得说一句insmod直接加载指定路径的模块不处理依赖modprobe会自动解析/lib/modules/$(uname -r)下的依赖关系。培训源码里模块少用insmod够了。4. 驱动调试避坑指南版本魔法字、节点缺失与设备树不生效4.1 现象编译模块提示 version magic 不匹配现象insmod一个编好的.ko终端返回version magic 4.19.66 should be 4.19.57或类似的错误模块加载失败。原因模块编译时使用的内核源码版本和开发板上运行的内核版本不一致。很多培训源码默认内核版本是固定的但开发板厂商后续升级过内核没同步更新资料里的内核树就会撞上这个错。另外内核配置里的CONFIG_MODVERSIONS和CONFIG_LOCALVERSION也会参与生成version magic字符串只要有一项不一样insmod就会拒绝。解决先用uname -r查看开发板内核版本再确认编译用的内核源码版本是否完全一致。一致之后确认内核源码的.config和开发板.config一致或者直接进入内核源码目录重新执行make modules_prepare后再编模块。临时方案是给内核传modprobe.force_unsafe_modules1强制加载但这只是绕过机制模块行为可能不可控不建议在生产环境用。4.2 现象insmod 成功但 /dev 节点没出现现象insmod没有报错lsmod也能看到模块但/dev下找不到对应设备节点应用程序打不开设备文件。原因驱动源码里没有class_create和device_create内核虽然注册了设备号但没有通过设备模型在用户空间建立节点。旧式教学代码图省事只做register_chrdev_region或者用了register_chrdev这个老接口不会自动生成节点。解决先cat /proc/devices看模块注册的设备号和名称然后用mknod手动创建。想彻底解决在驱动init函数里补上class_create和device_create两行并确保卸载时调用device_destroy和class_destroy。补完之后重新编译加载/dev节点就能自动出现不用每次手动建。4.3 现象设备树改了没生效设备根本没 probe现象修改了dts或dtsi文件编译并通过fastboot或tftp烧录了dtb重启后驱动probe函数没有被调用dmesg里啥也没有。原因最常见的原因是dtb烧进了boot分区但bootloader没加载新的dtb其次是dts里节点的compatible字段和驱动的of_match_table里的字符串不完全一致差一个字母都匹配不上。还有一种是节点状态没设为status okay默认的disabled会让内核直接跳过这个节点。解决先用开发板上的/proc/device-tree确认实际生效的dts内容ls /proc/device-tree/ cat /proc/device-tree/led/compatible cat /proc/device-tree/led/status如果/proc/device-tree里看不到led节点说明dtb根本没更新需要检查烧录分区。如果能看到节点但status是disabled改dts后重新编译。如果compatible值对不上直接把驱动of_match_table里的字符串改成和dts一致或者反过来两者必须完全逐字符相等。还有一个常见的坑是小写和大写compatible里.和-不能随意替换设备树匹配是严格字符串比较没有模糊匹配。4.4 现象模块加载就段错误大概率是编译器不一致现象insmod时开发板控制台直接提示segfault或者模块加载成功但访问设备时内核panic栈回溯显示在内核模块代码里。原因驱动模块用的交叉编译器和内核镜像的编译器不一致导致结构体对齐方式、内联函数展开、原子操作指令序列不兼容。最常见的情况是板子厂商用arm-linux-gnueabi-编译内核资料里给的驱动却用arm-linux-gnueabihf-编译hf和非hf的浮点ABI完全不同硬浮点模块加载到软浮点内核里必挂。解决查一下开发板内核的编译信息zcat /proc/config.gz | grep CONFIG_ARM cat /proc/self/auxv | grep -a HWCAP更直接的做法是看内核源码根目录的.config里CONFIG_AEABI和CONFIG_VFP配置然后选对应工具链。如果资料里同时给了多个编译器优先用内核编译时用的那个。实在没法确定时用buildroot重新生成一套工具链和内核虽然费时间但能保证ABI一致也算是最稳的后悔药。4.5 现象驱动里 printk 的信息日志看不到现象驱动加载或者读写时源码里写了printk但终端上什么都没打印。新手经常以为是printk没生效。原因printk有日志级别默认级别下的信息可能低于控制台的console_loglevel直接被内核过滤掉。调试信息一般用KERN_INFO或KERN_DEBUG而控制台默认只显示KERN_ERR以上级别。另外printk是进环形缓冲区的终端没显示不代表没记录可能被后续日志冲掉了。解决先dmesg | tail查内核日志缓冲区肯定能看到。想直接在终端实时看执行echo 8 /proc/sys/kernel/printk把console loglevel提到8所有级别都会显示。调试完记得调回默认值否则生产环境日志会被刷爆。驱动代码里推荐用dev_info(pdev-dev, ...)这类接口它自带设备名dmesg里一眼能看出是哪个设备在打日志比裸printk好用。5. 进阶阅读从源码里抠出中断、并发与延时设计5.1 中断上下半部tasklet 与 workqueue 的取舍这套源码里涉及按键和GPIO中断的驱动都会实现中断处理函数。中断处理有个铁律中断上下文里不能睡眠不能调用可能导致阻塞的函数。但实际硬件处理往往需要做耗时操作比如消抖、读取FIFO、通知用户态于是Linux把中断拆成上下半部。上半部是request_irq注册的处理函数要求短小精悍只做必须立即做的事。下半部延后处理可选机制包括tasklet、workqueue、threaded irq。源码里最常见的两种是tasklet和workqueue它们的区别很关键tasklet运行在软中断上下文不能睡眠workqueue运行在进程上下文可以睡眠。典型代码片段static void led_irq_work(struct work_struct *work) { /* 这里可以睡眠适合做较重的处理 */ enable_irq(irq_num); } static irqreturn_t led_irq_handler(int irq, void *dev_id) { schedule_work(led_work); disable_irq_nosync(irq_num); return IRQ_HANDLED; } static int led_probe(struct platform_device *pdev) { INIT_WORK(led_work, led_irq_work); ret request_irq(irq_num, led_irq_handler, IRQF_TRIGGER_FALLING, led_irq, led_data); return 0; }这个例程是“按键中断延时上报”的套路中断到来时上半部禁用中断并调度work下半部做实际处理后重新使能中断。disable_irq_nosync和enable_irq配对使用防止中断风暴。注意INIT_WORK必须在request_irq之前完成否则work还没初始化就被调度内核直接panic。实际项目里现在更推荐threaded irq用request_threaded_irq的handler传NULL、thread_fn传处理函数但老源码里tasklet和work这类教学写法更常见看懂它们再迁移到threaded irq并不难。5.2 并发控制自旋锁、信号量与互斥体在驱动里的边界驱动跑起来之后最隐蔽的bug来自并发。一个字符设备可能被多个进程同时open和read中断处理函数也可能和进程上下文同时访问同一块寄存器。这套源码里很多例程其实没做并发控制直接操作全局变量教学可以产品不行。理清锁的边界是进阶必须补的一课。自旋锁适合临界区极短、不会睡眠的场景比如中断处理函数里保护一个标志位互斥体适合进程上下文里访问共享数据临界区可能阻塞。错误用法是中断里拿mutex因为mutex睡眠会导致系统卡死。标准API对比/* 自旋锁用于原子上下文 */ spinlock_t lock; spin_lock_init(lock); spin_lock(lock); /* 临界区不能睡眠 */ port-status | BIT(1); spin_unlock(lock); /* 互斥体用于进程上下文 */ struct mutex mtx; mutex_init(mtx); mutex_lock(mtx); /* 临界区可以睡眠但不建议长时间持有 */ ret copy_to_user(buf, data, len); mutex_unlock(mtx);选锁的核心判断依据是“临界区里能不能睡眠”。如果临界区只有几行寄存器读写用自旋锁如果涉及copy_to_user、等待硬件完成、获取另一个锁就用互斥体。很多新人把自旋锁当成万能锁结果copy_to_user放进去直接死锁或报scheduling while atomic。源码里只要看到中断处理函数和普通read/write一起操作某个变量就该想到加锁。5.3 延时函数忙等、睡眠与内核时间精度驱动里做延时是高频操作比如操作I2C设备时要等从设备准备好操作LED时要产生闪烁波形。内核提供的延时函数分好几档用错会导致延时不准甚至系统崩溃。udelay是忙等基于CPU循环精度高但占用CPU只能用在原子上下文或延时极短的场景mdelay是udelay的多次调用也不睡眠msleep是睡眠式延时让出CPU只能进程上下文用usleep_range允许给一个范围内核可以更精确地唤醒。常见的坑是在中断处理函数里调用msleep直接触发内核错误。选择逻辑可以简单记短于几十微秒用udelay几十到几百微秒用usleep_range毫秒级以上且能睡就msleep。实际看这套源码消抖和时序控制大多用的udelay或mdelay因为按键消抖逻辑写在中断里不能睡眠。更合理的做法是把消抖放到workqueue里用msleep延时既准确又不占CPU。遇到这种代码理解它为什么这么写要比照抄更有价值。6. 最后按我的习惯源码应该按这个顺序读资料里的源码不会按照学习曲线排列目录顺序往往是按外设分类排的直接读很容易被复杂的平台设备驱动劝退。我自己拆过几套类似培训源码固定按“编译→最小模块→字符设备→设备树→中断”这个顺序推进效率高很多。第一步不管有多少个目录先把整个源码树的Makefile捋一遍找出哪几个模块能独立编译然后挑一个最接近“hello world”的驱动模块编出来、加载进板子。这一步的目标不是理解代码而是确认工具链和内核环境是通的。如果连最简单的模块都加载失败先把第4章的坑排查完再继续。第二步读这个最小模块的init和exit函数用dmesg观察加载和卸载日志。把module_init、module_exit、printk的加载顺序和日志输出对应起来驱动就不再是黑匣子了。第三步接触带硬件操作的字符设备驱动逐个看file_operations里的read/write/ioctl怎么操作寄存器。关键词是ioremap、writel、readl看到这三个函数说明驱动在直接访问物理地址。对照芯片手册的寄存器偏移能算出代码里写的地址对应哪个外设就算入门了。第四步读驱动里带probe函数的版本理解设备树匹配、platform_get_resource取资源这个过程然后对比老式固定地址驱动你就知道为什么要设备树了。第五步才去看中断、并发、延时这些进阶内容。我给你一个能验证学习效果的办法别只读动手删。把某个驱动里的device_create两行注释掉重新编译加载你会发现/dev下节点消失然后自己用mknod建一次恢复应用访问。这个实验做完你对设备模型的理解比看十遍书都深。再往后改改设备树里的interrupts属性看中断申请还成不成立这套驱动源码就算被你吃透了。这套资料不是拿来“看”的是拿来“拆”的。源码里每一个文件都可以被破坏性地修改再通过编译和运行结果反向验证理解。我从那以后每次拿到新的嵌入式源码都强制走一遍“先编译验证、再按依赖读、最后破坏性实验”的流程收获比从头到尾读代码大得多。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

MySQL表操作实战:从建表设计到结构变更的避坑指南

MySQL表操作实战:从建表设计到结构变更的避坑指南

最近帮朋友排查一个线上问题,他那个业务表才跑了几个月,数据量刚过百万,查询就慢得离谱。我上去一看,表结构稀烂:该用数字的用了字符串,时间字段没用索引,连主键都是带业务含义的字段&#xff0…

2026/10/14 19:21:40 阅读更多 →
AD工程文件与PCB设计实例:33例电路图+源代码快速上手

AD工程文件与PCB设计实例:33例电路图+源代码快速上手

简介:面向 Altium Designer 初学者的经典电路与单片机实例合集,以33个51单片机常见实验为主线,每个实例都配有电路图和可编译的 C/汇编源代码,适合从零学习原理图绘制、电路仿真与程序调试。实例内容由浅入深,覆盖流水…

2026/10/14 19:21:40 阅读更多 →
Linux挂载实战:从磁盘识别到fstab自动挂载与排错

Linux挂载实战:从磁盘识别到fstab自动挂载与排错

1. 从一次“磁盘满了”的误判说起很多人第一次接触 Linux 挂载,都是被一个看似简单的问题逼到墙角:明明买了一块大容量数据盘,系统却死活读不出来,或者重启之后数据莫名其妙“消失”了。我印象很深的一次,是帮一位做视…

2026/10/14 19:21:40 阅读更多 →

最新新闻

AI逆向工程实战:31.2K Star开源项目如何用大模型辅助二进制分析

AI逆向工程实战:31.2K Star开源项目如何用大模型辅助二进制分析

1. 当AI把目光投向二进制:逆向工程的门槛正在被重新定义第一次看到“AI开始搞逆向工程”这个说法,我的反应是:终于有人把这件事摆到台面上了。逆向工程这个领域,长期以来都是少数人的游戏——你得懂汇编,得熟悉PE/ELF文…

2026/10/14 23:16:08 阅读更多 →
ARM架构CentOS 7.6网口bond配置实战与优化指南

ARM架构CentOS 7.6网口bond配置实战与优化指南

1. 项目背景与需求拆解1.1 为什么要在ARM架构的CentOS 7.6上做网口bond在ARM服务器上跑CentOS 7.6,这个组合本身就有点意思。ARM架构的服务器这几年在数据中心里越来越常见,尤其是那些对功耗敏感、需要高密度部署的场景。但ARM平台跟传统的x86平台在硬件…

2026/10/14 23:16:08 阅读更多 →
两级式光伏MMC并网系统故障穿越Simulink仿真模型解析

两级式光伏MMC并网系统故障穿越Simulink仿真模型解析

1. 项目概述与问题背景做光伏并网研究的同学,对"故障穿越"这四个字应该都不陌生。无论你研究的是组串式逆变器、集中式逆变器,还是近几年大热的MMC拓扑,只要涉及并网,就绕不开电网故障时"能不能撑住、撑多久、怎么…

2026/10/14 23:16:08 阅读更多 →
AI Agent实操:五个新工具让AI学会用鼠标干活

AI Agent实操:五个新工具让AI学会用鼠标干活

1. 这次AI的进化方向,是先学会用鼠标Copilot能“直接操作”电脑这个事,让我琢磨了好几天。以前我们聊AI,聊的都是大模型能读多少token、能写多长的代码、能生成多像样的图。但那个层面的能力再强,它也是关在对话框里的——你问它答…

2026/10/14 23:16:08 阅读更多 →
OpenCV特征提取与匹配实战:SIFT、ORB、AKAZE选型与调参指南

OpenCV特征提取与匹配实战:SIFT、ORB、AKAZE选型与调参指南

1. 从一张拍歪的照片说起:为什么特征提取值得花时间搞懂很多人第一次接触OpenCV,都是从读图、灰度化、边缘检测这条线走下来的,觉得图像处理不过如此。直到某天需要把两张不同角度拍的同一场景对齐,或者想让程序在一堆商品图里找出…

2026/10/14 23:16:08 阅读更多 →
用Hermes Agent打造AI数字员工:企业自动化实战全解析

用Hermes Agent打造AI数字员工:企业自动化实战全解析

先交代一下背景,这个教程源自我在某企业内部做的一次 AI 自动化试点总结。当时团队的任务很直接,把重复性高、规则清晰但又需要人肉判断的活儿,逐步交给一套能听指挥、能调用工具、能自己干活的系统。市面上轮子很多,最终敲定用 H…

2026/10/14 23:14:55 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →