Представьте, что вы подключаете флешку или SSD к компьютеру. Через мгновение система уже показывает объем диска. Но как она это делает? Всё начинается с диалога между операционной системой и контроллером накопителя – крошечным «мозгом», который управляет хранением данных. Давайте разберемся, как это работает на низком уровне, и какие методы можно использовать в своих скриптах, если хочется обойтись без готовых библиотек.
Как диск сообщает о своих размерах
Каждый накопитель, будь то USB-флешка или NVMe SSD, содержит контроллер – микросхему, которая не только управляет чтением/записью, но и хранит служебную информацию. При подключении компьютер отправляет запрос по стандартному протоколу (SCSI, NVMe или ATA), а контроллер возвращает данные о емкости, числе секторов и других параметрах.
Например:
- NVMe использует команды
Identify Controller
иIdentify Namespace
, чтобы передать данные о пространстве. - SCSI (часто используется в USB-накопителях) опирается на команду
INQUIRY
и логические блоки (LBA). - SATA/IDE диски обмениваются информацией через протокол ATA, где ключевой является команда
IDENTIFY DEVICE
.
Кстати, операционная система не «изобретает велосипед» – она просто запрашивает эти данные при инициализации диска. Но если вы пишете скрипт, который должен работать на «голом» железе, придется взаимодействовать с контроллером напрямую.
Важно: Прямая отправка команд требует прав администратора (root в Linux) и глубокого понимания протоколов. Одна ошибка в структуре запроса – и вместо числа секторов получите I/O error.
Практические методы чтения данных без сторонних библиотек
Хотя теоретически можно отправлять raw-команды через ioctl (Linux) или DeviceIoControl (Windows), на практике проще использовать данные, которые ОС уже получила от диска. Вот несколько рабочих подходов:
1. Через системные утилиты (Linux):
На Linux информация о дисках хранится в каталоге /sys/block
. Например, чтобы узнать число секторов для /dev/sda
, выполните:
cat /sys/block/sda/size
Этот файл содержит общее количество 512-байтных секторов. Аналогичные данные можно получить из udev:
udevadm info --query=property --name=/dev/sda | grep ID_PART_TABLE_SIZE
2. Используя WinAPI (Windows):
В Windows можно обратиться к функции DeviceIoControl
с кодом IOCTL_DISK_GET_LENGTH_INFO
. Пример на Python (требуются права администратора):
import ctypes
kernel32 = ctypes.windll.kernel32
handle = kernel32.CreateFileW(r"\.PhysicalDrive0", 0x80000000, 3, None, 3, 0, None)
data = ctypes.create_string_buffer(8)
kernel32.DeviceIoControl(handle, 0x7405C, None, 0, data, 8, None, None)
sectors = int.from_bytes(data.raw, byteorder='little') // 512
print(sectors)
3. Парсинг выводов системных команд:
Если права ограничены, попробуйте получить данные через lsblk
(Linux) или wmic
(Windows):
lsblk -b --output SIZE /dev/sda
wmic diskdrive get size
Кстати, метод с попыткой записи в секторы – не лучшая идея. Во-первых, это может повредить данные. Во-вторых, некоторые диски «врут» о реальной емкости (особенно дешевые флешки), и запись в «несуществующие» секторы всё равно будет «успешной» (данные просто перезапишутся циклически).
Совет: Если скрипт должен работать на разных ОС, используйте кросс-платформенные методы – например, анализ вывода
sysctl
на macOS илиsmartctl
для S.M.A.R.T.-данных.
Итог: Не изобретайте велосипед – ОС уже собрала нужную информацию. Даже если очень хочется работать на низком уровне, готовые системные интерфейсы вроде udev или WMI сэкономят недели работы. А если всё-таки решитесь на raw-команды – запаситесь документацией по протоколам и кофе. И не забудьте про тесты для краевых случаев (например, диски с 4K секторами или RAID-массивы).