POSIX говорит "Система всегда заполняет нулями любую неполную страницу в конце объекта. Кроме того, система никогда не записывает какие-либо измененные части последней страницы объекта, которые выходят за его конец". , и документация Linux и FreeBSD имеет схожие формулировки на своих справочных страницах.
Это говорит о том, что, хотя чтение последних завершающих байтов не является строго законным (поскольку они находятся за пределами отображаемого диапазона), оно все же четко определено. и разработан таким образом, чтобы это могло работать без сбоев. Даже запись в эту область довольно четко определена.
Документация Windows, с другой стороны, ничего не говорит о конечных байтах в диапазоне меньше размера блока, и действительно предупреждает, что создание отображения большего размера, чем файл, увеличит размер файла и не обязательно обнулить данные.
Я склонен полагать, что это либо неверная информация, либо историческая (может быть, восходящая к Win95?). SetFileValidData
требует нестандартных прав пользователя из соображений безопасности, поскольку это может сделать данные из ранее удаленного файла видимыми. Если бы разработчики ядра Windows позволили кому-то тривиально обойти это, сопоставив любой случайный файл, они должны были бы быть довольно глупыми.
Мое наблюдение в Windows XP заключается в том, что любые новые страницы, по-видимому, извлекаются из нулевого пула, а для пустой страницы обратная запись, либо файл автоматически разрежается, либо обратная запись выполняется очень и очень интеллектуальным способом (без заметной задержки в любое время, даже в диапазоне гигабайт).
Так о чем вопрос?
Мне нужно вычислить хэш-значения (возможно, тысяч) файлов, чтобы обнаружить подмножество файлов, которые были изменены. Можно предположить, что в качестве алгоритма используется SHA-256, хотя фактический алгоритм не имеет особого значения.
Что само по себе, конечно, не является большой проблемой, но, как и любое программное обеспечение, оно должно запускаться в кратчайшие сроки и не использовать память, и поэтому на. Обычные реалистичные ожидания, вы поняли :-)
Обычный способ вычисления такого хэша состоит в том, чтобы проверить, соответствует ли размер сообщения размеру блока хеш-функции (скажем, 64 байта), и заполнить последний неполный блок нулями, если это не так. Кроме того, хэш может иметь требования к выравниванию.
Обычно это означает, что вы должны либо сделать полную копию сообщения, либо написать специальный код, который хэширует все блоки, кроме одного, плюс копию последнего блока, дополненную нулями. Или что-то подобное. Алгоритм хеширования также часто молча делает такие вещи от своего имени. В любом случае это связано с перемещением большого количества данных и большей сложностью, чем можно было бы ожидать.
Теперь есть соблазн напрямую хешировать отображаемый в память файл и полагаться на тот факт, что отображение файла обязательно зависит от страниц памяти. Таким образом, и начальный адрес, и физически отображенная длина более или менее гарантированно будут кратны 4 КБ (64 КБ в некоторых системах). Что, конечно же, означает, что они также автоматически кратны 64, 128 или любому другому размеру блока, который может иметь хеш.
И по соображениям безопасности ни одна ОС не может позволить себе предоставить вам страницу, содержащую устаревшие данные.
Это означает, что вы можете просто наивно хэшировать весь файл, не беспокоясь о выравнивании, заполнении или чем-то еще, и избегая копирования данных. Он может прочитать несколько байтов после конца отображаемого диапазона, но обязательно останется на той же странице.
Я, конечно, знаю, что это технически незаконно. Чтение последних байтов за пределами отображаемого диапазона в некоторой степени сравнимо с утверждением, что malloc(5)
в любом случае всегда возвращает 8-байтовый блок, поэтому безопасно использовать дополнительные 3 байта.
Хотя, помимо этой очевидной вещи, разумно ли мое предположение, что это будет «просто работать», или есть какая-то серьезная проблема, которую я не вижу ни на одной крупной платформе?
На самом деле меня не слишком интересуют теоретические или исторические операционные системы, но я хотел бы оставаться несколько портативным. То есть я хотел бы быть уверен, что он надежно работает на всем, с чем вы, вероятно, столкнетесь на настольном компьютере или на «типичном хостинг-сервере» (то есть в основном на Windows, Linux, BSD, OSX).
Если существует операционная система 1985 года, которая помечает последнюю страницу как нечитаемую и применяет строгие диапазоны байтов в своем обработчике ошибок, я согласен с этим. Вы не можете (и не должны) сделать всех счастливыми.