Меня интересует эффективность поиска

В настоящее время я изучаю структуру PE. Я пытаюсь разобрать это, используя perl вместо C.

Это не важно, но если вы читаете бинарный файл, вы должны перейти к определенному разделу. (Например, чтобы прочитать e_lfanew)

Я хочу прочитать данные в точке 0x78, которые читаются $buf с данными 0x200.

Вот два способа, которыми я думал, чтобы извлечь данные по адресу 0x78.

my ($ dummy, $ data) = unpack ("A0x78 A*", $buf);
or
seek (F, 0x78,0); read F, $buf, 0x200; print ~

Я хочу знать, какой из двух методов более эффективен, чем вычитание фиктивных данных и чтение данных и чтение новых данных через поиск.


person SAnji Holic    schedule 16.02.2019    source источник
comment
(1) Эталон и Time::HiRes (2) То, что вы показываете, несравнимо: в одном случае вы используете unpack, в другом read данные; (независимо от буферизации) вы сравниваете работу в памяти с чтением с диска? Последнее предложение непонятно.   -  person zdim    schedule 16.02.2019
comment
Совет: используйте x вместо A, чтобы пропускать байты, не возвращая их.   -  person ikegami    schedule 16.02.2019
comment
Совет: используйте a вместо A для двоичных данных. A удалит конечные 0x20 байта   -  person ikegami    schedule 16.02.2019
comment
Это оставляет вас с my $data = unpack("x0x78 a*", $buf);   -  person ikegami    schedule 16.02.2019
comment
вау, я впервые заметил функцию распаковки под названием «x». Спасибо, что дали мне знать   -  person SAnji Holic    schedule 16.02.2019


Ответы (1)


Минимальная единица хранения на диске называется сектором. Для жестких дисков они обычно имеют размер 512 байт (хотя вы также можете найти диски с секторами по 4096 байт).

Ваш файл занимает два сектора.

000  078       200   278      400
+--------------+--------------+---...
|    ****************
+--------------+--------------+---...

А поскольку интересующий блок частично находится в первом секторе, оба подхода, которые вы описали, должны будут прочитать одинаковое количество секторов.

Поскольку на самом деле чтение данных с диска является медленной частью, между этими двумя подходами нет реальной разницы.


О, но вы буферизуете ввод-вывод вместо использования sysread. При использовании буферизованного ввода-вывода (например, read) Perl читает из ОС кусками по 4 КиБ или 8 КиБ (в зависимости от вашей версии Perl). Таким образом, 8 или 16 секторов загружаются с диска, если вы начинаете чтение с позиции 0, и 9 или 17 секторов загружаются с диска, если вы seek сначала. Таким образом, пытаясь читать меньше, вы на самом деле читаете больше!

Тем не менее, разница настолько мала, что разница в скорости должна быть потеряна в шуме.

person ikegami    schedule 16.02.2019