Linux:C语言直接访问硬盘
我如何获得对硬盘的原始访问权限并知道该位置是否已被使用或者是可用空间? 仅举一个例子,我只需在磁盘设备上进行打开和读取即可获得直接访问,目标是了解是否使用了例如 10.000 字节。
How can I obtain a raw access to the HD and know if that location is used or is a free space?
Just a piece of example, I can obtain a direct access simply with an open and a read on a disk device, the goal is knowing whether the, for example, 10.000 byte is used or not.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您只需
打开
块设备(例如,/dev/sda
)并手动读取扇区。 但是,这不会直接告诉您它是否为空。 是否为空是在文件系统抽象级别定义的。 文件系统数据结构存储此类数据,您应该对特定文件系统有深入的了解,才能从原始块中执行此操作(不使用任何文件系统提供的功能)。You can just
open
the block device (for example,/dev/sda
) and read the sectors manually. However, that won't tell tell you if it's empty or not directly. Being empty or not is a something defined at the filesystem abstraction level. File system data structures store that kind of data and you should have a deep understanding of the specific filesystem to do so from the raw blocks (without using any filesystem provided function).补充一下注意事项...
不要忘记,您必须与现有驱动程序堆栈自己的线程安全规定和内部缓存配合。 系统中的许多线程可以(并且将会)一直写入磁盘。 要擦除自由扇区,您必须知道它是自由的,并在您随心所欲地使用它时保持自由。 如果您擦除了文件系统已决定使用的扇区,但尚未将该决定的证据刷新到磁盘,因此您无法知道它正在使用,那就糟糕了。 这可能会导致数据丢失,从而引起用户的愤怒。
如果您可以保证当前未安装文件系统,那么至少原则上您可以打开
/dev/sda
(可能不是您想要的特定文件系统!)并解析磁盘上的数据结构以执行您需要执行的任何操作。 这实际上就是fsck
和mkfs
等实用程序的实现方式。剩下的大问题是您必须与可能遇到的每个文件系统的每个版本保持同步。 至少您有文件系统本身的源代码可供参考,但将其从内核移植到用户模式应用程序中并不容易。
我的建议是使用文件系统本身来获得所需的保证。 打开大文件并用您的划像图案填充它们。 将磁盘填满。 请注意,如果这可能对任何正在运行的守护程序(假设有一些磁盘空间可用)产生严重影响,那么可能仍然需要在大多数守护程序被杀死的系统上完成此操作。 如果您的目标是安全擦除,您仍然需要担心在两次传递之间实际将写入的块刷新到磁盘,因为普通文件系统中的所有内容都会尝试优化单个块的多次写入。
To pile on with the cautions...
Don't forget that you have to cooperate with the existing driver stack's own thread safety provisions and internal caching. Many threads in the system can (and will) be writing to the disk all the time. To wipe a free sector, you have to know it to be free and stay free while you have your way with it. It would be bad if you wiped a sector that the file system had already decided to use, but hadn't flushed the evidence of that decision out to disk yet so you had no way to know it was in use. This could result in data loss which can result in outraged users.
If you can guarantee that the file system is currently not mounted then you can, in principle at least, open
/dev/sda
(probably not the specific one you want!) and parse the on-disk data structures to do anything you need to do. This is actually how utilities likefsck
andmkfs
are implemented.The remaining big issue is that you have to stay in sync with every version of every file system you might encounter. At least you have the source code available for the file system itself for reference, but it will not be easy to just port it out of the kernel and into a user-mode application.
My advice would be to use the file system itself to get you the guarantees you need. Open large files and fill them with your wipe patterns. Fill the disk to capacity. Note that if this might have a serious impact on any running daemons that assume that some disk space is available, so it might still need to be done on a system with most daemons and such killed. If you are aiming for a secure wipe, you will still need to worry about actually flushing the written blocks to disk between passes because everything in the normal file system is going to try to optimize multiple writes of a single block.
您很可能不想直接通过 /dev/sd* 或 /dev/hd* 访问块设备。 正如其他人所说,您必须了解原始的底层文件系统,这将非常困难。
如果您正在编写一个应用程序,希望将磁盘上的字节视为一个大的线性地址空间,那么请查看 mmap() 系统调用。 您可以在磁盘上创建一个大的空文件,然后使用 mmap() 将其映射到进程空间。 从那里,您可以使用常规内存操作来读取和写入底层大文件。 请注意,写入是缓冲的,因此保证一致性可能很棘手。
这种方法的优点是,即使底层文件是碎片化的,您的访问模式也可以将其视为字节的线性集合。
In all likelyhood, you don't want to access the block device via /dev/sd* or /dev/hd* directly. As others stated, you'll have to understand the raw underlying filesystem, and this will be very difficult.
If you're writing an application that wants to treat bytes on disk as a big linear address space, then check out the mmap() system call. You can create a large, empty file on disk, and then use mmap() to map it into your process space. From there, you can use regular memory operations to read and write to the underlying large file. Note that writes are buffered, so guaranteeing consistency can be tricky.
The advantage of this approach is that even if the underlying file is fragmented, your access pattern(s) can consider it as a linear collection of bytes.
如果您想擦除文件系统中的所有可用空间,可以用一个全是零的大文件填充文件系统,将其同步到磁盘,然后将其删除。 这可能并不能完全解决所有问题,特别是如果您正在处理日志文件系统等,但它可以完成大部分工作。 如果您想擦除磁盘以便更好地压缩图像,这可能就是您需要做的全部事情。 如果您出于安全原因想要清理磁盘...欢迎来到内核开发的世界,请深入探讨,并记住穿一些阻燃的衣服。
有一个名为 zerofree 的实用程序可以清零ext 文件系统中的空闲块,适用于 VM 映像。 请记住,这不是您应该对已安装的文件系统执行的操作。 该页面还有一些旧的内核补丁,这可能是在实时文件系统上执行此操作的一个有趣的起点。
If you're wanting to wipe all the free space in a filesystem, you can fill the filesystem with one big file full of zeros, sync it to disk, and then delete it. That may not get absolutely everything, particularly if you are dealing with a logging filesystem or the like, but it will do most of it. If you're wanting to wipe the disk so an image compresses better, this is probably all you need to do. If you're wanting to clean the disk for security reasons... welcome to the world of kernel development, please step into the deep end, and remember to wear something flame resistant.
There is a utility called zerofree to zero out free blocks in ext filesystems, and is intended for VM images. Remember, this is not something you should do to a mounted fileystem. That page also has some old kernel patches that might prove an interesting starting point for doing this on live filesystems.
天啊。
您的代码必须:
如果我是你,我会重新考虑你想要做什么。
编辑:看到他对他实际上想做的事情的评论,
OH MY.
Your code would have to:
If I were you I'd reconsider what you are trying to do.
EDIT: seeing his comment for what he's actually trying to do,
非常依赖于许多因素,例如
解决方案:
Very dependent on lots of factors such as
Solutions:
您也许可以利用文件系统和/或磁盘工具检查某个位置是否空闲的相同功能。
You might be able to utilise the same functions that the file system and/or disk tools use to check if a location is free or not.