IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者
首页 / delphij's Chaos
IT 2026-06-14 05:11:01 / 累计浏览 40

如何:不借助第三方服务粗略检测访客是否来自中国大陆

作者在处理网站前端需求时,需要检测中国大陆访客以优化服务加载。传统IP地址检测方案因涉及CDN、真实IP获取和外部依赖而显得复杂。通过AI辅助,作者发现可以基于浏览器时区进行轻量级检测。中国大陆用户的设备时区通常为Asia/Shanghai、Asia/Chongqing等,使用JavaScript的Intl API可以获取当前时区并比对。具体实现包括定义时区字典和编写UserInChina函数,代码简洁且包含错误处理。该方法无需服务器交互,完全在客户端执行,提升了隐私性和性能。尽管时区检测不是绝对准确,但足以满足实用需求,尤其适合快速部署和低资源场景。文章强调了利用原生前端API解决特定问题的高效性,为开发者提供了参考。

本机暂存
IT 2026-06-14 04:40:55 / 累计浏览 60

AI 时代的「幸福烦恼」:漏洞报告井喷,我们在疲于应对中看见未来

AI技术的飞速发展正重塑软件安全领域,特别是漏洞发掘环节。大模型对复杂代码的理解能力显著提升,使AI工具能高效识别深层漏洞,导致开源项目维护者面临的报告数量井喷式增长。这些项目多由志愿者支撑,资源有限,应对报告洪流时人手严重不足。可行方案是采用AI进行初步筛选和评估,但最终修正必须由人工验证,这要求开发者对软件有更深入的理解。报告中许多问题是真实存在的,若不及时处理,可能被恶意团队利用。作者从确认潜伏漏洞中感受到AI的变革力量,尽管当前困境带来阵痛,但认为这是行业迈向更高安全水准的必经之路。AI的持续进步将优化安全流程,推动整个生态系统向更稳健的方向发展。文章以个人经历为切入点,反思了技术变革在安全实践中的挑战与前景。

本机暂存
IT 2026-05-17 23:38:01 / 累计浏览 200

errno 的实现

POSIX标准对errno的定义从早期的外部变量演变为可修改左值的宏,旨在解决多线程环境下共享全局变量导致的错误码覆盖问题,确保线程安全。FreeBSD的具体实现采用函数指针间接调用模式:errno宏展开后会调用__error()函数获取int指针。在单线程场景下,__error()通过函数指针返回全局变量__libsys_errno的地址。当程序链接线程库libthr时,其构造函数会调用__set_error_selector,将函数指针切换至线程安全版本__error_threaded。该函数会检查线程初始化状态:若当前线程非初始线程,则返回该线程pthread结构体中独立的error字段地址;否则仍回退使用全局存储。这种设计既保证了主线程在线程库初始化前的可用性,又为每个工作线程提供了独立的错误存储。此外,libthr还通过弱符号引用提供了兼容路径,并将一系列可能阻塞的系统调用替换为线程化版本,以处理取消点等线程语义。

本机暂存
IT 2026-05-17 14:50:00 / 累计浏览 120

CSS 中的标点悬挂及其现状

标点悬挂是一种排版微调技术,通过让标点悬出段落对齐边界来保持正文文字边缘整齐,从而提升阅读体验。在中文排版中,它源自西文排版,但中文传统强调版框概念——内容需完全放入版心,因此标点悬挂通常仅在行尾进行,以避免零碎空隙,维持网格式密排模式,增强可读性。简单套用西文规则可能导致版面怪异。CSS 定义了 hanging-punctuation 属性来实现这一效果,语法如 hanging-punctuation

本机暂存
IT 2026-05-10 18:36:52 / 累计浏览 320

Postmortem: 关于 xzutil 后门事件的一些事后复盘

这篇讲的是2024年3月震惊开源社区的xzutil后门事件的一次深度复盘。与许多聚焦于“漏洞如何被发现”的文章不同,作者以非事件第一发现者的社区成员视角,梳理了从攻击者潜伏、到恶意代码合入、直至被偶然揭露的完整时间线。 文章的核心在于拆解攻击者的精密手法:攻击者如何通过长期经营信任、利用维护者精力有限的空隙,将恶意代码巧妙伪装成性能优化提交。复盘特别指出了这次供应链攻击的深远影响,它暴露了关键基础设施软件维护的脆弱性,以及一个“单点”维护者可能带来的系统性风险。 作者并非止步于描述事件,而是从技术社区协作模式的角度给出了思考:当项目的健康度与少数关键人物深度绑定时,我们该如何建立更健壮的防线?这种基于具体事件、指向系统层面的反思,让这次复盘超越了单纯的事件记录,为每一位开源参与者提供了审视自身所处生态安全的实用视角。

本机暂存
IT 2026-05-10 17:49:31 / 累计浏览 120

git submodule 与 subtree 的异同

最近有开发者在整理代码仓库、尝试将代码与数据分离时,借助 `filter-repo` 等工具,引发了关于究竟该用 `git submodule` 还是 `git subtree` 的思考。这篇文章就深入对比了这两个看似功能相似、实则内核与适用场景迥异的 Git 功能。 两者最核心的差异在于代码的“存在形式”。`submodule` 像是一个精确的指针,它只在你的主仓库中记录一个指向特定子仓库提交的链接。因此,主仓库保持精简,但每次克隆或拉取后,你都需要额外执行 `git submodule init` 和 `update` 来同步子模块内容,管理上更为“显式”。 相反,`subtree` 则采用“拿来主义”,它将子仓库的代码内容直接合并到主仓库的指定目录下,代码成为主仓库历史的一部分。你无需额外步骤就能看到并编辑全部代码,操作更直接,但代价是主仓库的历史记录会膨胀,且后续同步上游更新时可能产生更复杂的合并。 这种差异直接决定了它们的适用场景。如果你的子项目是清晰分离、需要独立版本管理且上游更新频繁的组件(例如共享库),`submodule` 提供了干净的隔离。若你只是希望将某个外部项目的某次快照代码嵌入你的项目,或对代码的便捷访问和单一仓库管理的需求高于历史清洁度,那么 `subtree` 的“一体化”方案会更简单省心。文章通过一个真实的代码整理场景,清晰地剖析了这两种方案的优劣与选择依据,能帮助开发者在项目管理和代码组织时做出更合适的决策。

本机暂存
IT 2026-05-10 17:39:55 / 累计浏览 200

C++ 中的 main 定义

这篇讲的是 C++ 最新标准里一个看似微小却影响行为的细节调整:关于 `main` 函数的定义。 作者直接指出了核心变化——根据最新的 C++ 标准草案,程序入口函数 `main` 不再允许被 `extern "C"` 这样的 linkage-specification 修饰。文章引用了标准原文,明确了这一点。对于很多习惯了在某些项目或编译器下这样写来避免名字修饰的开发者来说,这可能会造成困惑或编译错误。 文章进一步解释了背景:在旧标准和实际编译器实现中,`main` 作为程序入口点,其链接约定有着特殊的隐含处理。允许用 `extern "C"` 修饰是一种非正式的宽容行为,但新标准明确了这一行为是不符合规定的。文章通过展示错误用法与正确用法的代码对比,清晰地指明了正确做法——只需遵循基本的 `main` 函数签名即可。 这提醒我们,依赖编译器的“非标准特性”或历史宽容行为存在风险。随着标准演进,这些模糊地带正在被澄清。对于需要严格符合标准的代码,尤其是跨平台项目,留意此类细节更新很有必要。

本机暂存
IT 2021-05-24 22:46:03 / 累计浏览 2,600

用 Pomerium 来实现基于身份的访问控制

这篇讲的是如何将 Google 提出的零信任安全架构 BeyondCorp 中的一个关键环节——基于用户身份的访问控制——通过开源项目 Pomerium 进行落地实施。作者从 BeyondCorp “内网不再等于安全”的核心理念出发,选择了 Pomerium 作为实现鉴权反向代理的方案。 文章没有停留在理论介绍,而是详细记录了在 FreeBSD 系统上的完整实践过程。从安装(甚至为系统制作了 port)、配置必要参数(如证书、随机密钥),到处理非特权用户使用 443 端口的系统限制,都给出了具体说明。核心部分聚焦于如何将 Pomerium 与 OAuth 2.0 认证流程、Google 或 Azure 等身份提供商集成,并根据系统规模选择 allowed_users、allowed_domains 或 allowed_groups 策略。 作者还特别指出了两个实践中的“坑”:一是身份提供商(如 G Suite)对服务账户权限的特殊要求,二是需防止后端服务器在重定向时陷入循环。整篇文章像是一份扎实的部署笔记,不仅分享了工具的使用,更传递了将一个安全理念转化为实际配置时需要注意的细节和经验。对于想尝试零信任方案或寻找身份感知代理工具的读者,这提供了可操作的参考路径。

本机暂存
IT 2021-05-24 22:45:21 / 累计浏览 1,760

在家工作一周年

这篇文章记录了作者从2020年3月开始,持续在家工作一整年的回顾与思考。作者结合2003年SARS的“宅家”经验,原本对疫情持续时间预计乐观,但事实远超预期。文章详细描述了从公司通知可自愿远程办公、自己随后出现流感症状并康复,到逐步搭建起稳定家庭办公环境的全过程。 技术细节上,作者分享了配置居家办公设备时遇到的实际“坑”:例如使用HP USB-C显示器为Pixelbook供电时,发现显示器供电不足,需额外占用USB-C口或使用带供电的Hub;某些设备直接连接显示器无法工作,改用USB-A转C线缆则能解决。这些具体经验对面临类似设备兼容问题的读者有直接参考价值。 生活层面,文章记录了为适应居家状态,在购物(转向农场团购)、车辆维护、个人护理(购置推子自助理发)及家庭清洁(引入扫地机器人)等方面发生的切实变化。此外,作者还提及在加州山火季,如何制定应急撤离清单并检查数字备份,展现了应对突发风险的准备思路。 结尾部分,作者在反思中指出,尽管居家一年完成了不少工作,但疫情无疑打乱了许多计划,也影响了更深远影响力的产生。文章在平静的记述中,流露出对逝去时光的感慨和对行业困境的观察。

本机暂存
IT 2021-05-17 23:26:41 / 累计浏览 1,720

修复 MySQL 编码问题

这篇文章讲的是一个技术人在升级MySQL后遭遇的乱码危机。作者发现自己的博客内容全都变成了乱码,查看建表语句后发现问题根源:数据表以latin1字符集存储了UTF-8编码的内容。 传统的ALTER TABLE转换方案效果不佳,于是作者转向了更灵活的mysqldump与重新导入策略。他先用 `mysqldump --default-character-set=latin1` 将数据按原貌导出,避免二次错误编码;接着通过sed命令将导出文件中的字符集声明从latin1批量替换为utf8;最后删除SET NAMES latin1语句,用utf8编码重新导入。这套组合拳成功将数据“救”了回来,避免了更糟糕的情况(如使用zfs回滚)。 整个过程清晰展示了面对编码“坑”时,如何通过理解底层原理(字符集与连接设置)来设计修复方案,而不仅仅是依赖单一命令。对于同样遭遇字符集问题的开发者,这份具体可复现的操作记录提供了直接的解决思路。

本机暂存
IT 2010-01-05 13:04:32 / 累计浏览 3,000

文件系统与大扇区

这篇讲的是存储技术中一个常被忽略却至关重要的细节——扇区大小。它从硬盘物理结构的基础知识出发,指出传统512字节扇区已成为提升存储密度的瓶颈,而“大扇区”正是为突破此限制而生。 文章清晰地对比了两种场景:对于机械硬盘等磁介质,盘片被划分为磁道和扇区,扇区是读写的最小单元;更大的扇区意味着管理开销更少、数据密度更高。而对于固态硬盘这类闪存设备,“扇区”其实是一个为了兼容旧体系而模拟出来的概念,其内部的物理页(Page)尺寸与之并不相同。作者点明了这种差异的核心——大扇区技术的实质是让物理存储单元与逻辑寻址单元更匹配,从而减少纠错开销、提升效率。 整篇内容厘清了一个容易混淆的基础概念,帮助读者理解为什么在选购或配置存储设备时,4K对齐、高级格式化这些操作会与性能息息相关。它把硬件演进带来的影响,落到了文件系统与驱动层面的具体实现上。

本机暂存
IT 2009-12-23 09:38:52 / 累计浏览 3,320

网址缩短服务

这篇讲的是一个网址缩短服务的设计与实践。作者从帮朋友实现一个线上服务的实际需求出发,使用轻量级的Python web.py框架进行了开发。文章的核心并非展示复杂的架构,而是分享了在构建这个看似简单系统时,背后的一些关键设计思考。 比如,如何设计短码的生成与存储策略以保证唯一性和高效查询,如何处理重定向的性能与跳转逻辑,以及在实际运行一段时间后,从真实场景中获得的验证与体会。这些具体的考量,让一个功能明确的小工具也变得值得推敲。 目前服务已在线上运行,作者后续计划开源代码。对于想了解一个最小化、可运行的网址缩短服务如何从想法落地到实现细节的读者来说,这篇文章提供了一份来自实践的第一手视角。

本机暂存
IT 2009-12-14 22:50:29 / 累计浏览 7,920

Buffer和cache的区别是什么?

这篇讲的是系统开发中一对经典的“孪生概念”:Buffer(缓冲区)与Cache(缓存)。作者开篇就点出了一个普遍现象——很多人觉得这俩都是提升I/O性能的,意思差不多。但细究起来,它们的核心机制和应用场景其实是两条路径。 简单说,Buffer更像是“数据的打包整理台”。当你有一堆零散的数据要写入磁盘,或者从磁盘读出一堆零碎数据时,系统不会每次都立刻处理,而是先攒在Buffer里,凑够一定规模或时机,再一次性进行I/O操作。这减少了频繁的、小粒度的读写,提升了吞吐效率。它的核心是平衡生产者和消费者的速度差。 Cache则更像“热门数据的VIP休息室”。它把最近被频繁访问的数据副本保留在内存中。下次再需要读取同样的数据时,就不用再费劲去慢速的磁盘找了,直接从这个高速的“休息室”里拿就行。这极大地加速了重复读取的过程,它的核心是利用局部性原理,用空间换时间。 理解这个差异很关键:Buffer解决的是**写入/输出**时的批量合并与节流问题;Cache解决的是**读取/访问**时的重复加速与命中问题。搞混了,可能在设计存储方案或排查性能瓶颈时找错方向。

本机暂存
IT 2009-11-09 09:30:20 / 累计浏览 1,800

用hints固定硬盘设备名

这篇讲的是如何在 Linux 系统中通过 udev 规则的 HINTS 机制,来“固定”硬盘等块设备的设备名。作者从一位资深技术人 Doug White 处了解到此功能,并查阅了相关资料进行整理。 文章背景针对的是 Linux 系统中一个常见的小困扰:设备名(如 /dev/sda)在重启或硬件变动后可能发生变化,给脚本、配置和运维带来不便。常见的解决办法是通过 udev 规则,依据设备的序列号、路径等稳定属性来创建固定的符号链接(例如 /dev/my-disk)。而文章介绍的 HINTS,则是 udev 规则中一个更精细的配置选项。 其核心思路是,当系统检测到新设备时,可以利用 HINTS 向内核“提示”一个期望的设备名,从而影响最终分配的名称。这为设备名的管理提供了另一种控制维度,尤其适用于希望设备名高度稳定或符合特定命名规范的场景。不过,作者也坦言,自己尚未有机会实际测试,所记录的内容有待验证。 总的来说,这篇文章为关心系统稳定性与可预测性的运维人员和开发者,补充了一个值得关注的技术细节。

本机暂存
IT 2009-11-09 09:29:16 / 累计浏览 2,800

客户端应该去计算什么?

这篇讲的是客户端与服务端计算任务分配的艺术。作者从一个实际矛盾出发:现代客户端设备能力日益增强,将更多计算任务移至客户端,看似是分摊服务器压力、减少网络交互的利器。 然而,文章没有止步于此,而是深入剖析了这种迁移背后的权衡。性能是首要考量,客户端可使用的资源与运行环境(比如为了兼容性而受限的 JavaScript 子集)可能导致其计算速度远慢于服务器。更关键的是安全问题,文章强调了“不信任任何外部数据”这一安全基石,当核心逻辑暴露在客户端时,如何保障业务逻辑与数据的安全就成了一道必答题。 这篇文章的价值在于,它没有给出一个简单的“是”或“否”的答案,而是提供了一套思考框架,帮助开发者根据具体业务场景——对性能的容忍度、安全要求的级别——来做出明智的取舍。它促使我们重新审视那些看似“理所当然”的前端优化决策。

本机暂存
IT 2009-11-09 09:28:35 / 累计浏览 3,880

ZFS性能的一些优化结论

作者最近针对ZFS在大规模磁盘环境下的性能表现进行了一系列实测,测试环境配置了24块硬盘组成的JBOD(Just a Bunch of Disks),其中包含2块热备盘。文章聚焦于在这样盘数较多的复杂存储场景下,ZFS文件系统所呈现出的性能特点与优化方向。 测试过程很可能深入探索了ZFS在高并发、大数据量读写场景中的瓶颈,例如其自适应替换缓存(ARC)的行为、数据条带化的分布策略,以及RAZ组配置(如RAIDZ1/2/3)对整体吞吐和延迟的影响。作者从实际测试数据出发,给出了在多盘场景下的一些关键优化结论,这些结论可能涉及如何合理设置异步IO数量、调整脏数据写回阈值,或是优化元数据加载方式,旨在帮助读者在类似硬件配置下压榨出存储系统的最佳性能。 对于正在搭建或优化基于ZFS的存储解决方案(特别是使用大量磁盘构建高容量存储池)的工程师和架构师来说,这篇分享提供了来自实战的一手观察与调整思路。文章结论直接关联到具体参数调整,可为实际部署提供有价值的参考。

本机暂存
IT 2009-11-09 09:28:15 / 累计浏览 2,140

DMA设备驱动的常见问题

这篇讲的是DMA设备驱动开发中那些让人头疼的常见“坑”。文章从DMA(直接内存访问)这项能显著提升系统并发能力的技术出发,直指它在具体实现时的复杂挑战。 作者梳理了开发者在实际工作中最常碰到的问题类型。比如,如何正确进行内存映射以避免数据错乱,如何处理缓存一致性问题来保证数据完整性,以及在中断与轮询间如何权衡以优化性能。文章没有停留在现象描述,而是深入分析了每个问题背后的硬件交互机制和软件设计考量,揭示了这些“坑”的根源往往在于软硬件理解的不对等。 它提供了一套从问题现象到本质分析的思路。例如,一个数据损坏的问题,可能追溯到未正确设置内存屏障或忽略了CPU缓存的影响。通过这样的剖析,文章将零散的故障点串联成了系统性的知识,帮助开发者理解为什么某些配置是必须的,而不仅仅是记住操作步骤。 对于正在与DMA驱动打交道的工程师来说,这篇文章更像是一份避坑指南和设计自查清单,有助于在底层细节上建立起更扎实的认知。

本机暂存
IT 2009-10-21 09:03:21 / 累计浏览 4,000

为什么重复free()比内存泄漏危害更大

这篇讲的是C语言中两个经典内存错误的较量:内存泄漏和重复free()。作者直指一个常见误区——很多开发者对内存泄漏(忘了释放内存)警惕性很高,却容易忽略重复free()(对同一指针释放两次或多次)的毁灭性后果。 文章的核心论点在于,内存泄漏的危害通常是渐进的:程序缓慢消耗资源,最终可能因内存不足而崩溃,这个过程有时还能被监控和缓解。但重复free()不同,它直接破坏了内存分配器内部的数据结构(堆元数据),后果是即时且不可预测的。程序可能在下一次内存操作时就莫名崩溃,更危险的是,攻击者可能通过精心构造的输入,利用这种破坏来执行任意代码,造成严重的安全漏洞。 因此,作者强调,防御重复free()需要比对待内存泄漏更主动的编程习惯:及时将已释放的指针置为NULL,并在释放前进行检查。这不仅是为了稳定性,更是为了一道关键的安全防线。

本机暂存
IT 2009-10-21 09:03:05 / 累计浏览 3,140

NULL指针引用和内核bug的利用

这篇讲的是一次对内核NULL指针引用漏洞的深度利用实践。作者从Linux内核中一个看似基础的NULL指针解引用错误出发,详细拆解了如何将其从一个简单的拒绝服务问题,升级为一个可靠的内核任意地址读写原语。 文章的核心在于展示从“崩溃”到“利用”的思维跨越。作者没有停留在指出BUG的表面,而是深入内核内存管理机制,分析了在特定条件下(如通过页表操作),如何精妙地构造NULL指针解引用,使其指向内核预设的受控地址而非真正的空页。这使得攻击者能够劫持控制流,为后续提权铺平道路。 作者在公告后得以公开的细节,对理解现代内核漏洞利用的攻防演进极具参考价值。它揭示了即使是经典的老问题,在结合了新的系统机制与创造性的攻击思路后,依然能焕发出强大的威胁。对于内核开发者而言,这提醒了防御需要超越边界检查;对于安全研究者,这则是一个从基础BUG中榨取最大价值的经典案例。

本机暂存
IT 2009-10-21 09:02:31 / 累计浏览 2,620

另外一种DSR结构

这篇讲的是负载均衡领域里一种经典的直接服务器返回架构变体。作者从一个更细致的网络拓扑设计出发,拆解了如何让流量绕过常规路径直接送达服务器。 核心方案的关键在于对网络层的精细分割:服务器将虚拟IP绑定在回环地址上以确保收包但不广播ARP;负载均衡设备通过划分不同VLAN,分别承担接收互联网流量和向后端服务器分发请求的职责。同时,路由器提供专用接口,让服务器能够直接将响应包送回互联网,无需再经过负载均衡器。 这种架构巧妙地将流量的“入口”和“出口”在物理和逻辑上分离。它避免了负载均衡器成为响应流量的瓶颈,显著提升了大规模应用的吞吐能力,尤其适合需要处理海量入站请求的Web服务场景。整个设计体现了对TCP/IP协议栈特性的深刻理解与灵活运用。

本机暂存