WMI: Win32_DiskDrive для получения общего сектора на физическом диске - PullRequest
3 голосов
/ 28 марта 2012

Я попытался получить максимальный общий сектор диска, используя Win32_DiskDrive , но все они возвращают неправильное значение. Я использовал HxD , и эта программа возвращает точное значение. Я попытался получить общий сектор в Linux с помощью fdisk, он также вернул точно.

Я заметил, что в MSDN Win32_DiskDrive есть примечание:

значение для этого свойства получается через расширенные функции прерывания BIOS 13h. Это значение может быть неточным, если накопитель использует схему преобразования для поддержки дисков большой емкости. Обратитесь к производителю за точными характеристиками привода.

Но я не мог понять, что это значит? и как решить эту проблему?

Обновление 1:

Вот фрагмент кода моего скрипта Python.

Обязательно: Python , PyWin32 , WMI

import wmi

c = wmi.WMI()
for diskDrive in c.query("SELECT * FROM Win32_DiskDrive"):
    print diskDrive.Name, "\nTotal Sector: ", diskDrive.TotalSectors

Обновление 2:

В соответствии с запросом приведен фрагмент WMI с обнаруженным сектором HxD.

  • WMI: 625137345 (вверху)
  • HxD: 625142448 (внизу)

Sector Difference Screenshot

Обновление 3:

Если кому-то интересно, вы также можете попробовать это на своем компьютере и посмотреть, сообщает ли Win32_DiskDrive точный результат. Я пробовал это на многих других компьютерах (WinXP & 7) с другим устройством хранения (жесткий диск, флэш-диск и т.

Чтобы попробовать, пожалуйста, установите Python , PyWin32 , WMI

Большое спасибо

Ответы [ 2 ]

2 голосов
/ 25 февраля 2015

WMI сообщает, что диски на несколько МБ меньше, чем они есть на самом деле.Я думаю, что это связано с тем, как Windows обрабатывает диск с точки зрения цилиндров / головок / секторов.

Мое решение состояло в том, чтобы прочитать после окончания указанного размера диска, пока я не получу ошибку:

import wmi
disks = wmi.WMI().Win32_DiskDrive(MediaType="Removable Media")
for disk in disks:
    disk_size = int(disk.size)
    sector_size = disk.BytesPerSector
    print(disk.name, "reported size:", disk_size)
    with open(disk.name, "rb") as f:
        f.seek(disk_size)
        while True:
            try:
                f.read(sector_size)
                disk_size += sector_size
            except PermissionError:
                break
    print(disk.name, "readable size:", disk_size)

Я получаю следующий результат для двух разных 32 ГБ SD-карт:

\\.\PHYSICALDRIVE2 reported size: 31683778560
\\.\PHYSICALDRIVE2 readable size: 31691110400
\\.\PHYSICALDRIVE3 reported size: 31437020160
\\.\PHYSICALDRIVE3 readable size: 31439453184

Однако на реальных дисках фактически есть дополнительные 1024–2048 байтов, которые мы до сих пор не можем прочитать, и я 'Я не уверен, как их получить.Однако это лучше, чем несколько МБ, которые мы пропускали раньше.

Редактировать: Похоже, что буферизация вызывала проблему с чтением последних нескольких байтов.Я могу прочитать оставшиеся байты, если я сделаю open(disk.name, "rb", buffering=0).Однако это было очень медленно (~ 1 МБ / с, что составляет около 7 секунд для одного из дисков).Вероятно, есть хороший гибридный подход, в котором вы используете только буферизацию = 0 для чтения последних нескольких байтов, а остальное время используете буферизацию по умолчанию.

\\.\PHYSICALDRIVE2 reported size: 31683778560
\\.\PHYSICALDRIVE2 readable size: 31691112448 (with buffering=0)
\\.\PHYSICALDRIVE14 reported size: 31437020160
\\.\PHYSICALDRIVE14 readable size: 31439454208 (with buffering=0)

Редактировать 2: Вы можете получить последние несколько байтов, используя read1, без необходимости открывать файл с помощью buffering=0.Таким образом, чтобы получить фактический размер диска, вы можете сделать следующее:

reported_size = disk.size
f.seek(reported_size)
while True:
    try:  # Read beyond the reported size
        f.read(sector_size)
    except PermissionError:
        easily_readable_size = f.tell()
        try:  # Get the last few bytes using read1 (unbuffered)
            for i in range(128):  # Test up to this many additional sectors
                f.read1(self.sector_size)
        except PermissionError:
            actual_size = f.tell()
            break

Заметьте, я думаю , что вы не всегда сможете от f.read до easily_readable_size с момента выравниванияиз внутренних буферов не всегда могут быть одинаковыми (?).Я уменьшил это значение на io.DEFAULT_BUFFER_SIZE, чтобы быть немного безопаснее.Затем я переписал f.read своей собственной функцией, которая делает комбинацию вышеупомянутых вещей прозрачной f.read правильно по всему диску.Таким образом, f.read работает так, как вы ожидаете, что он будет работать в первую очередь.

0 голосов
/ 29 марта 2012

Вы говорите, как этот фрагмент не работает для конкретного жесткого диска?Можете ли вы дать нам подробную информацию об этом жестком диске и о том, как вы знаете, что он неправильный.

Однако попробуйте вместо этого использовать чистый подход winapi.DeviceIoControl может использоваться для этого комфортно .Смотрите полный список кодов в cpp.

Я знаю, что есть способ написать c ++ на python, так что удачи:)

...