Linux:用C直接访问硬盘

Posted

技术标签:

【中文标题】Linux:用C直接访问硬盘【英文标题】:Linux: direct access to the hard-disk in C 【发布时间】:2010-11-01 22:42:16 【问题描述】:

如何获得对 HD 的原始访问权限并知道该位置是否已被使用或是否为可用空间? 举个例子,我可以简单地通过打开和读取磁盘设备来获得直接访问,目标是知道是否使用了例如 10.000 字节。

【问题讨论】:

为什么要这样做?从标签来看,您似乎要编写一个设备驱动程序。如果它是一个新的文件系统,那么好吧,太好了,写到 /dev/sd*。更多应用程序级别的详细信息将有助于获得更好的答案。 我将构建一个可用空间擦除器,只是为了重置磁盘上的所有非用户空间。如果您定期销毁过去在磁盘上执行的所有操作,则非常有用。在我自己的情况下,我使用的是 ext3 FS。 你确定没有这样的雨刷吗? 我从来没有为 ext FS 找到任何类型的擦除器 【参考方案1】:

您可以只open 块设备(例如/dev/sda)并手动读取扇区。但是,这不会直接告诉您它是否为空。是否为空是在文件系统抽象级别定义的。文件系统数据结构存储此类数据,您应该从原始块(不使用任何文件系统提供的功能)深入了解特定文件系统。

【讨论】:

【参考方案2】:

继续注意事项...

不要忘记,您必须配合现有驱动程序堆栈自己的线程安全规定和内部缓存。系统中的许多线程可以(并且将)一直在写入磁盘。要擦除一个免费扇区,您必须知道它是免费的,并且在您随心所欲地使用它时保持免费。如果您擦除了文件系统已经决定使用的扇区,但还没有将该决定的证据刷新到磁盘上,那么您无法知道它正在使用中,那将是很糟糕的。这可能会导致数据丢失,从而导致用户愤怒。

如果您可以保证文件系统当前未挂载,那么您至少原则上可以打开/dev/sda(可能不是您想要的特定系统!)并解析on-磁盘数据结构可以做任何你需要做的事情。这实际上是fsckmkfs 等实用程序的实现方式。

剩下的大问题是您必须与可能遇到的每个文件系统的每个版本保持同步。至少您有可供文件系统本身参考的源代码,但仅将其从内核移植到用户模式应用程序中并不容易。

我的建议是使用文件系统本身来为您提供所需的保证。打开大文件并用您的擦除模式填充它们。将磁盘填满。请注意,如果这可能对假设某些磁盘空间可用的任何正在运行的守护程序产生严重影响,那么它可能仍需要在具有大多数守护程序且此类被杀死的系统上完成。如果您的目标是安全擦除,您仍然需要担心在两次传递之间实际将写入的块刷新到磁盘,因为普通文件系统中的所有内容都会尝试优化单个块的多次写入。

【讨论】:

【参考方案3】:

您很可能不想通过 /dev/sd* 或 /dev/hd* 直接访问块设备。正如其他人所说,您必须了解原始的底层文件系统,这将非常困难。

如果您正在编写一个应用程序,希望将磁盘上的字节视为一个大的线性地址空间,那么请查看 mmap() 系统调用。您可以在磁盘上创建一个大的空文件,然后使用 mmap() 将其映射到您的进程空间。从那里,您可以使用常规内存操作来读取和写入底层大文件。请注意,写入是缓冲的,因此保证一致性可能很棘手。

这种方法的优点是即使底层文件是碎片化的,您的访问模式也可以将其视为字节的线性集合。

【讨论】:

【参考方案4】:

如果您想擦除文件系统中的所有可用空间,您可以用一个充满零的大文件填充文件系统,将其同步到磁盘,然后将其删除。这可能无法完全解决所有问题,特别是如果您正在处理日志文件系统等,但它会完成大部分工作。如果您想擦除磁盘以便更好地压缩图像,这可能就是您需要做的所有事情。如果您出于安全原因想清理磁盘...欢迎来到内核开发的世界,请深入了解一下,并记得戴上阻燃的东西。

有一个名为zerofree 的实用程序可以将 ext 文件系统中的空闲块清零,并且适用于 VM 映像。请记住,这不是您应该对已挂载的文件系统执行的操作。该页面还包含一些旧内核补丁,这些补丁可能是在实时文件系统上执行此操作的有趣起点。

【讨论】:

谢谢,如果您不关心性能,这是一个很好的解决方案。我想象过的最好的解决方案是开发一个守护进程,并在空闲时间随机进入磁盘并“擦除”。这并不容易,但很有趣.... 当它随机进入一个正在用于关键事物(例如内核)的扇区时,它会变得真正令人兴奋 ;-)【参考方案5】:

天哪。

您的代码必须:

    遍历分区表以查看属于哪个分区。 确定它是什么类型的文件系统。 对于您支持的每个文件系统,提供这样一个例程来查看该字节是否正在使用中 检查文件系统是否已挂载 如果是,则遍历内核记录以查明是否有尚未写入磁盘的内容。 哦,如果你使用的是EXT4或REISER,你不知道前面的答案,所以你还不如放弃。

如果我是你,我会重新考虑你想要做什么。

编辑:看到他对他实际尝试做的事情的评论,

接受分区而不是原始磁盘 需要下马 调用 e3fsck 来汇总日志 遍历每个 inode,找到最后一个块并擦除该块中的所有可用空间(文件大小应说明数据在块中的结束位置) 遍历分配位图,找到任何未分配的块并擦除它们 现在是棘手的部分,擦拭日志。 祝你好运 哦,请阅读文件系统文档

【讨论】:

好吧...我正在尝试做这样一种程序来擦除所有可用空间,一个磁盘擦除器。我想到的第一种也是很糟糕的方法是长时间遍历所有磁盘,检查哪些部分是空闲的并重置它们。【参考方案6】:

很大程度上取决于很多因素,例如

文件系统类型 操作系统类型 中型

解决方案:

对于 ext2 和 ext3:https://superuser.com/questions/130912/how-do-i-determine-what-file-occupies-a-given-sector-in-linux 对于 NTFS:https://superuser.com/questions/97823/how-do-i-determine-what-file-occupies-a-given-sector

【讨论】:

【参考方案7】:

您也许可以利用文件系统和/或磁盘工具用来检查某个位置是否空闲的相同功能。

【讨论】:

以上是关于Linux:用C直接访问硬盘的主要内容,如果未能解决你的问题,请参考以下文章

CentOS LVM逻辑卷管理

挂载是啥意思?

Linux学习基础知识

使用硬盘快速访问替代 RAM

查看磁盘空间命令

hyper-v 扩展硬盘问题