IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

标签:文件系统

共 35 篇相关文章

IT 累计浏览 76

Windows 95 defenses against installers that overwrite a file with an older version

早期16位Windows系统中,许多系统组件可由程序安装包分发,导致程序安装程序常直接覆盖系统文件,可能将Windows 95组件替换为更旧的版本。Windows 95通过建立隐藏的备份目录SYSBCKUP来应对:安装程序完成后,系统会检测关键文件是否被覆盖;若新覆盖文件的版本高于备份版本,则将其存入备份目录;若版本较低,则用备份文件还原,从而防止系统组件被降级。此前曾尝试直接阻止覆盖操作,但引发了更多兼容性问题,最终采用“先允许覆盖、后自动修复”的策略更为有效。

IT 累计浏览 1,239

Linux 文件系统详解

这篇讲的是Linux文件系统,作者从1996年的亲身经历切入:当时他学会了安装软件,却对/etc、/usr这些“神秘目录”的含义一头雾水。文章的目的就是帮助新手快速搞清楚这套结构。 不同于纯理论讲解,作者推荐了一个非常具体的起点:在终端安装并运行`tree`命令,尤其是`tree -L 1 /`,能立刻直观展示从根目录开始的、清晰的一级目录树。接着,文章对/bin(用户基本工具)、/boot(启动文件,警告别乱动)、/etc(系统配置)、/home(用户个人文件)等核心目录逐一拆解,解释了它们的用途和命名由来。 文中还穿插了不少实用细节,比如现代发行版中/bin和/usr/bin的趋同关系,/tmp是少数无需root权限即可操作的目录,以及/srv等特定服务数据的存放位置。作者的口吻带着老技术人的风趣,比如调侃自己对新工具“不以为然”,但整体非常务实,旨在帮读者快速建立对Linux文件系统的结构化认知,避免当初自己踩过的坑。

IT 累计浏览 3,067

为什么 Windows 的文件系统会有盘符,使用反斜杠分割路径

这篇技术博客从一个轻松的讨论切入——Windows系统在挂载大量盘符后会出现双字母命名的“诡异”现象,进而探讨其背后的设计逻辑。作者指出,虽然从现代视角看,盘符和反斜杠似乎是冗余的历史包袱,但其根源深植于MS-DOS的早期发展。 文章追溯到MS-DOS 1.0时代,当时主流软盘没有层级目录。盘符(A:、B:)的设计直接借鉴了更早的CP/M系统,方便用户在两个软盘驱动器间操作。随着IBM PC/XT引入10MB硬盘,盘符扩展到了C:。而路径分隔符选用反斜杠“\”而非Unix的“/”,是因为MS-DOS的开发者继承了DEC系统使用“/”作为命令行参数分隔符的惯例,为避免混淆,只能选择其他符号作为目录分隔符。 作者通过这段历史对比了Windows与Unix系系统的设计哲学:Unix将物理存储通过挂载点透明地整合进统一文件树,而Windows保留了显式的盘符概念。这些早期设计决策,最终形成了我们今天看到的、让不少程序员感到“深恶痛绝”的Windows路径风格。

IT 累计浏览 2,339

find命令详解

这篇讲的是Linux系统里人人都会用、但未必人人都精通的`find`命令。作者开篇就直指那些让很多人困惑的细节:比如`find / -mtime +7`和`find / -mtime -7`到底在找什么?为什么`-exec`后面有时是`{}`加`+`,有时是`{}`加`\;`? 文章的核心是把`find`的参数拆解成四大类:Tests(条件测试)、Actions(执行动作)、全局选项和位置选项。重点落在Tests部分,这里把时间参数讲得非常透彻。`-mtime 7`并不是“修改于7天前”,而是“修改时间落在当前往前第7个24小时那个区间内”;加上`+`号就变成了“大于7天前”,加上`-`号则是“7天以内”。这种对数字范围的精确界定,是很多教程一笔带过的。文章还对比了`-anewer`、`-newer`等不同时间比较参数的用法,甚至提到了`-newerXY`这种能跨时区比较(如修改时间对比变更时间)的进阶技巧。 除了时间,文章也梳理了如何按用户、权限来筛选文件,并穿插了`-ls`、`-exec`等常用动作的实际案例。整体来说,它不是一份简单的命令手册,而是通过厘清易混淆的概念(尤其是时间参数和`-exec`的语法),帮助读者把`find`从“会用”提升到“精准使用”的层次。对于需要经常处理文件系统的运维或开发人员,这些细节差异直接决定了命令的成败。

IT 累计浏览 4,753

分布式存储Seaweedfs源码分析

这篇文章对分布式文件存储系统 SeaweedFS 0.67 版本的源码进行了一次深入的解剖。作者从其基于 Facebook Haystack 论文的架构思想出发,指出 SeaweedFS 实现了“青出于蓝而胜于蓝”的改进。 文章清晰地梳理了项目的核心模块,重点剖析了其两大支柱:拓扑管理与数据存储。在拓扑层面,详解了由 DataCenter、Rack、DataNode 构成的树状结构,这正是其管理分布式 VolumeServer 的核心。而在数据存储层面,则层层递进,解释了文件唯一标识 Fid 的构成(VolumeId, NeedleId, Cookie),并深入到 Volume 文件内部的布局——SuperBlock 与 Needle 的关系。特别值得一提的是,文中对 SuperBlock 中 TTL(Time To Live)功能的实现原理进行了拆解,阐述了如何通过 Volume 级别的超时标记与清理机制来优雅地实现文件的定时删除。 整体来看,这篇文章并未停留在功能介绍,而是直击代码,帮助读者理解 SeaweedFS 如何用简洁的设计实现高性能的对象存储,对于理解分布式存储系统的工程实现很有参考价值。

IT 累计浏览 1,577

资源包的设计

这篇讲的是游戏资源包设计中的工程实践与权衡。作者从“如何把资源打包并高效更新”这一核心问题出发,指出了当前直接使用通用压缩格式(如zip)的普遍做法,以及为应对资源引用关系、大量文件检索等需求而采用自定义格式(如MPQ、AssetBundle)的趋势,其中对文件名进行hash索引是关键一步。 然而,文章敏锐地指出,hash冲突是这类设计中不容回避的问题,并以Unity的AssetBundle在冲突时直接放弃打包为例,说明了现有方案的缺陷。作者随后提出了一种简单有效的“加盐二次hash”方案:在打包时若发现hash冲突,便引入一个可确定的salt值重新计算,从而在运行时能唯一区分原文件,且强调了正确加盐(如将salt作为hash seed或循环XOR)的重要性,避免了简单拼接导致的二次冲突。 此外,文章还涵盖了资源包间的引用需依赖间接索引而非单纯hash值,以及patch更新可设计为保留完整索引的增量包、并定期生成基准全量包的策略。最后,作者将打包工具类比为git,需要实现初始化、文件追踪、版本打包与diff生成等版本管理功能。整体方案兼顾了理论基础与工程落地,对处理游戏资源管理的复杂性提供了清晰的思路。

IT 累计浏览 3,643

Linux,du、df统计的硬盘使用情况不一致问题

在Linux服务器上用`du`统计目录大小只有2G,但`df`显示硬盘却已占用3G甚至更多,这种不一致让不少运维同学困惑过。这篇文章就系统地拆解了背后的三大元凶。 首先是ext文件系统预留的“急救空间”。这部分空间`df`会计入已用,但`du`完全感知不到,作者指明了如何用`tune2fs`查看和调整这个数值。 其次是“幻影文件”。当文件被删除但进程句柄未释放时,`du`已经不统计它了,但磁盘块仍被`df`计算在内。文中给出了通过`lsof`查找这类文件并处理进程的方法。 最隐蔽的是第三种情况:在目录挂载新设备前,如果其中已有数据,这些数据会被“隐藏”——`du`和`df`在新设备上都看不见它们,但它们实实在在占用了原设备的空间。文章详细说明了如何安全地卸载、清理这些残留数据。 这篇文章从运维中一个看似小、却容易让人卡住的矛盾点切入,清晰梳理了原理和排障路径。理解了这些机制,下次再遇到`du`和`df`“打架”,你就能快速定位是哪一种情况,并对症处理了。

IT 累计浏览 2,138

教你如何在Windiws平台上创建以点(.)开头的文件名

Windows系统有个小脾气:当你想创建像.gitignore这样以点开头的配置文件时,如果直接输入文件名,系统会弹出“文件名不能以点开头”的错误提示。这给需要管理隐藏配置文件的开发者带来了困扰。 这篇教程分享了一个非常巧妙的解决方法:在命名时,在期望的文件名(例如.gitignore)末尾**再添加一个点**,将其输入为“.gitignore.”。这样,文件就能成功创建,并且系统会自动识别并保留真正的“.gitignore”这个文件名。这个技巧利用了Windows文件命名规则中的一个小盲区,虽然简单,却有效解决了实际问题。 需要注意的是,这个方法在Windows资源管理器中操作有效,但更适合需要看到文件扩展名的程序员用户。对于普通用户,通常可以通过命令行或其他方式达到目的。这个小技巧体现了在技术实践中,有时绕过表面限制、理解系统底层行为,能找到意想不到的简便解法。

IT 累计浏览 3,880

linux下cp,mv进行动态库覆盖问题分析

这篇讲的是一个生产环境中典型的“隐形地雷”:明明只是想更新一个动态库文件(.so),为什么用 cp 命令覆盖后,正在运行的程序就莫名崩溃了?作者从一次周会讨论的问题出发,抽丝剥茧地分析了这个现象的深层原因。 文章先厘清了 Linux 文件系统的两个关键概念:inode 存储文件元数据,dentry 建立文件名到 inode 的映射。核心分析由此展开:cp 和 mv 操作对正在被进程使用的文件影响截然不同。cp 命令本质是“打开目标文件并截断,然后写入新数据”,这个截断操作会通知内核释放该文件在内存中的所有页面映射。当程序再次执行到该库的代码时,会触发缺页中断,但因为原文件数据块已失效,内核无法正确填充内存,于是导致总线错误(bus error)或段错误(segment fault)。相比之下,mv 命令仅仅是重命名操作,只改变了目录项(dentry)的指向,并未影响文件本身(inode)及其内存映射,因此是安全的。 文章通过 strace 跟踪和进程内存映射的视角,清晰展示了故障现场。结论很明确:对于已被进程动态链接的库文件,在线更新的正确姿势是 mv(将新文件重命名为原名),而不是 cp。

IT 累计浏览 3,272

Linux内核中通过文件描述符获取绝对路径

这篇深入探讨了一个内核开发中具体且实用的场景:当你只知道一个进程的pid和它持有的某个文件描述符fd时,如何在内核里一步步找回该文件在磁盘上的绝对路径。 文章的核心思路是沿着内核的数据结构进行“导航”。它首先通过pid找到进程的task_struct,再从中取出进程打开的文件表files_struct。以fd为索引,就能定位到代表这个文件的内核结构体file。接下来是最关键的两步:从file中获取封装了dentry(目录项)和挂载点信息的path结构,并最终调用内核函数`d_path()`,将这一系列结构解析为人类可读的绝对路径字符串。 整个实现过程清晰展示了Linux内核管理进程与文件系统的精巧层次。这种从进程到文件、再到路径的逆向追踪能力,对于调试内核模块、进行系统监控或编写特定内核功能来说,是一项非常基础且重要的技术。

IT 累计浏览 2,646

ext4+delalloc造成单次写延迟增加的分析

这篇讲的是淘宝内核组在将线上系统升级到Ext4文件系统后,发现应用写操作延迟异常增大的故障。根源在于Ext4的新特性“延迟分配”(delalloc)。 简单来说,delalloc为了优化后续的顺序访问性能,将原本每次写操作都会进行的磁盘块分配过程,推迟到了系统批量回写数据时才进行。这导致了一个关键的锁竞争问题:回写进程在批量分配磁盘块时需要持有排他写锁(i_data_sem),这个过程可能耗时较长(例如约30秒一次)。如果此时有应用程序发起新的写操作,它就必须等待这把锁释放,从而导致单次写操作的延迟被显著拉高。 作者通过fio工具进行了量化测试:开启delalloc后,虽然写操作的平均延迟更低(5.86微秒 vs 7.00微秒),但最大延迟却飙升到了193毫秒,是关闭时(16毫秒)的10倍以上。这清晰地说明了delalloc“集中处理”带来的长尾延迟问题。 对于使用Buffer IO进行追加写、不主动刷新数据且对延迟敏感的应用,这个问题会尤为突出。文章给出的解决方法是在挂载时加上`nodelloc`参数来关闭此特性。

IT 累计浏览 3,184

FUSE源码剖析

这篇讲的是如何通过源码剖析来理解FUSE(用户空间文件系统)的内部工作原理。作者以FUSE-2.9.2版本的代码为基础,没有停留在概念介绍,而是直接切入核心,详细拆解了一个文件写操作在内核与用户空间之间完整往返的8个步骤。 文章清晰地梳理了从应用层发起write系统调用开始,请求如何经由VFS层传递给FUSE内核模块,被放入请求队列并等待,再到用户空间的守护进程轮询获取请求、执行实际操作,最后将结果同步返回内核的整个链条。这个视角生动展示了FUSE作为“桥梁”的实现机制。 为了支撑流程讲解,文章系统地介绍了内核侧与用户侧的关键数据结构,如管理通信连接的fuse\_conn、代表单次请求的fuse\_req等,勾勒出了FUSE框架的数据骨架。此外,文章还剖析了FUSE内核模块的加载注册过程,以及用户态程序通过mount命令将自定义文件系统挂载到内核的流程,从底层揭示了用户态文件系统得以运行的根基。 通过这样自顶向下与自底向上结合的剖析,文章将FUSE看似复杂的跨空间协作,还原为一组清晰的数据结构和函数调用,为理解这类“中间件”的设计思想提供了绝佳范例。

IT 累计浏览 3,638

bash遍历目录

作者从实际需求出发,整理了两套用纯Bash遍历目录树的方法:深度优先(DFS)和广度优先(BFS)。文章坦言,对于大多数简单操作,`find`命令组合其他工具足矣;但当需要严格控制遍历顺序,或者执行的操作逻辑比较复杂时,手动实现遍历就很有必要。 文中的两个函数提供了清晰的模板。作者特别指出一个实用的细节:循环中使用`` `ls "$dir"` ``而非通配符`"$dir"/*`,是为了避免当目录为空时,循环体需要额外判断`dentry`是否存在,让代码更简洁。BFS版本使用队列结构,DFS版本则用栈来模拟递归。 更巧妙的是,作者通过将回调函数作为参数传入,让遍历逻辑与具体任务解耦。示例中展示了如何用它们实现一个统计C/C++项目代码行数的脚本。文章追溯了这些代码的起源——从早年为FVWM桌面窗口管理器生成文件树菜单,到后来因ext3迁移ext4后修复文件权限而反复打磨,这些脚本在解决具体问题的过程中不断演进。对于有类似定制化需求的运维或开发人员,这份经过实践检验的代码片段值得参考。

IT 累计浏览 5,378

为什么Linux不需要磁盘碎片整理

这篇讲的是为什么Linux系统几乎不需要磁盘碎片整理。作者从Linux和Windows文件系统的核心设计差异出发,解释了Linux文件系统(如ext4)如何通过智能机制避免碎片产生。例如,ext4采用块分配算法,在写入时尽量将文件数据连续放置在磁盘上,同时结合延迟分配技术——系统会暂存写入请求,待收集足够数据后再一次性分配,从而大幅减少碎片。此外,Linux的inode和块组结构有助于优化存储布局,保持文件局部性。相比之下,Windows的NTFS文件系统在频繁安装、删除或修改文件后,容易产生碎片,导致磁头频繁寻道,性能下降,因此需要定期运行碎片整理工具来重组数据。 文章指出,这种设计差异让Linux在长期运行中碎片率极低,提升了I/O效率,同时也让用户省去了维护碎片整理的负担。对于系统管理员或从Windows转来的用户而言,这意味着在Linux环境下可以更专注于应用开发和日常使用,而不必担心磁盘性能退化。整体上,这篇内容通过具体的技术对比,清晰揭示了Linux存储管理的优势,提供了实用的操作系统见解。

IT 累计浏览 3,550

Linux 核心编程 – fsync, write

这篇技术博客聚焦于 Linux 系统编程中两个至关重要却又容易混淆的底层函数:`write` 与 `fsync`。文章没有停留在概念表面,而是直接从 `write` 的函数签名切入,详细剖析了其 `fd`、`buf`、`count` 各参数的含义与常见陷阱,并重点解释了 `ssize_t` 返回值背后可能遇到的短写(short write)问题及其应对策略。 核心对比则围绕 `write` 与 `fsync` 展开。作者清晰地指出了两者的关键区别:`write` 通常只将数据从用户空间缓冲区拷贝到内核页缓存,操作成功并不代表数据已持久化到磁盘;而 `fsync` 则强制将指定文件描述符的所有修改冲洗到物理存储设备,是保障数据完整性的最后一道关卡。文章结合数据库事务日志、日志文件追加等真实场景,说明了在何种情况下必须调用 `fsync` 来确保可靠性,以及滥用它可能带来的性能影响。 全文通过具体的函数行为分析和场景化讨论,将这两个基础系统调用的工作机制和正确使用姿势讲得透彻明白,对于需要编写高可靠性 I/O 代码的开发者而言,是一篇能帮助厘清底层细节、避免潜在 bug 的实用指南。

IT 累计浏览 8,089

C语言中史上最愚蠢的Bug

这篇讲的是一个号称“史上最愚蠢”的C语言Bug,但它却有着极强的迷惑性,以至于作者本人——一位经验丰富的开发者——都亲手写下了这段错误代码。文章揭示的这类错误通常源于一个微小的疏忽:可能是少写了一对括号,忽略了运算符优先级,或是对宏展开的理解出现了偏差。最令人“拍案惊奇”的是,这类Bug往往能通过编译,甚至在部分环境下“碰巧”正常工作,从而成为代码库中隐藏的定时炸弹。作者通过亲身经历提醒我们,无论经验多丰富,在C语言(乃至所有编程语言)的细节面前都需保持敬畏。真正的陷阱,常常就藏在我们认为“绝对不可能出错”的地方。

IT 累计浏览 3,828

linux中为何没有网卡设备文件

这篇讲的是一个看似简单却让很多人好奇的系统细节:为什么在Linux/Unix中,我们能看到硬盘的/dev/sda,却找不到网卡对应的设备文件?作者从这个问题切入,带读者回顾了网络设备在Unix哲学中独特的抽象历史。 文章并没有给出一个高深的技术答案,而是揭示了背后的思考。核心观点在于,Unix将网络设备(如eth0)抽象为字符设备或块设备,而是通过套接字(socket)接口统一管理,这是一种更高层次的抽象,更符合网络通信的流式与协议特性。作者通过这个细节,带出了对早期Unix设计者如何平衡硬件抽象与网络通信模型的思考。 这不仅仅是一个历史冷知识。它能帮助我们理解,现代操作系统中许多“理所当然”的设计(比如ifconfig和ip命令)并非凭空而来,而是源于清晰的设计哲学。对于开发者和运维人员来说,理解这种设计意图,能让我们更深刻地把握系统的行为逻辑。

IT 累计浏览 2,940

调研分享:图片文件在各文件系统上的访问性能对比

这篇讲的是不同文件系统在处理图片这类静态小文件时的访问性能实测与对比。作者从实际生产需求出发,对比了ext4、XFS、Btrfs、ZFS以及NVMeoF等文件系统,核心关注的是图片读写、元数据操作等典型场景下的性能差异。 测试使用了fio等工具,覆盖了顺序写、随机读等关键维度。结果显示,传统文件系统如ext4和XFS在元数据密集型操作(如stat)上依然有很强的优势,尤其适合需要高频随机读取大量小文件的Web服务器场景。而Btrfs和ZFS这类现代文件系统,虽然在快照、校验等高级功能上更丰富,但在纯性能上会为这些功能付出一定开销。对于特定场景如海量图片存储,ZFS的ARC缓存机制则能带来可观的读取性能提升。 文章最后没有给出一个“通用最优解”,而是指出选择需权衡:追求极致元数据性能的可选ext4/XFS,需要数据完整性与高级管理的可以考虑Btrfs/ZFS,而对于超大规模的图片CDN,NVMeoF等分布式方案则打开了新的可能性。这些基于实测的差异,能为技术选型提供一个清晰的参考坐标。

IT 累计浏览 8,511

提升磁盘IO性能的几个技巧

这篇文章从最基础的磁盘工作原理出发,剖析了影响其IO性能的核心因素。它指出,由于机械磁盘依赖物理寻道来定位数据,这个过程的速度直接决定了性能上限——因此,磁盘的随机读写速度会显著低于顺序读写。文章特别强调,磁盘自带的读写缓存容量是另一个关键指标,更大的缓存能有效缓冲读写请求,提升突发传输效率。 基于这些特性,文章进一步将原理关联到实际的系统设计场景中。作者提醒开发者,在进行架构或应用设计时,必须理解并利用磁盘的这一“偏科”特性:应尽量通过优化数据布局和访问模式,将随机IO转化为顺序IO,从而充分发挥硬件效能。这不仅是针对传统机械硬盘的认知,也为理解存储优化策略提供了基础视角。

IT 累计浏览 3,771

linux环境下使用GFS文件系统

这篇文章从Linux环境下的实际存储需求切入,探讨了GFS(Global File System)这一网络文件系统的应用。GFS允许将多台计算机连接到同一个共享存储设备上,像使用本地磁盘一样访问统一的数据。作者详细解释了GFS的核心特性,比如它如何提供高可用性和负载均衡,以及通过分布式锁机制确保多节点并发访问时的数据一致性。 文中具体分析了GFS相较于传统本地文件系统(如ext4)或简单NFS方案的优势。GFS更适合需要多机共享大容量数据的场景,例如高性能计算集群、Web服务器集群或数据库存储后端,它能有效避免单点存储瓶颈。同时,文章也客观指出了其配置和运维的复杂度,更适合有一定技术基础的团队。 对于正在设计高可用架构或面临存储扩展难题的读者来说,这篇文章清晰地梳理了GFS的定位和典型用例,为技术选型提供了务实的参考。