2014-01-22 4 views
10

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

Однако эта практика также кажется принципиально небезопасной, если вы не можете гарантировать, что никакой другой процесс не будет записывать в сопоставленный файл, потому что даже данные в частных сопоставлениях только для чтения могут измениться, если основной файл написан другим процессом. (POSIX, например, doesn't specify «независимо от того, были ли изменения в базовом объекте, выполненные после установления MAP_PRIVATE, отображаются через MAP_PRIVATE mapping».)

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

Правильно ли этот анализ? Документация для API сопоставления памяти обычно упоминает эту проблему только мимоходом, если вообще, поэтому я задаюсь вопросом, не хватает ли я чего-то.

+0

Это возможно для другого процесса изменения файла во время его использования. Картирование памяти - это один из самых разных способов использования файла - он не более опасен, чем любой другой. – Casey

+1

Копирование содержимого файла с помощью обычных API-интерфейсов чтения в буфер памяти всегда безопасно, даже если файл одновременно изменяется. Напротив, если вы получаете доступ к файлу с отображением памяти с помощью обычных указателей, а внешний процесс одновременно его модифицирует, вы получаете неопределенное поведение, потому что это не связано с ограничениями модели памяти C (++).Как правило, если память, которую вы или ваш компилятор ожидаете постоянных изменений под ногами, произойдет плохо. Вход, который вы подтвердите за один момент, может стать недействительным в следующий момент. –

+0

Вы неверно истолковываете цель 'MAP_PRIVATE'. Это не значит, что я даю мне частную копию * это означает, что сделанные мной модификации являются частными для меня **. Он имеет все те же проблемы параллелизма, что и любой другой метод для доступа к файлу. – Petesh

ответ

1

Это не проблема.

Да, другой процесс может изменить файл во время его сопоставления, и, возможно, вы увидите изменения. Это даже , вероятно,, так как почти все операционные системы имеют унифицированные системы виртуальной памяти, поэтому, если вы не запрашиваете небуферизованные записи, нет способа писать, не пройдя через буферный кеш, и никоим образом не будет, если кто-то будет иметь сопоставление, видя изменение.
Это даже не плохая вещь. На самом деле, было бы более тревожным, если бы вы не смогли посмотреть изменения. Так как файл quasi становится частью вашего адресного пространства при его сопоставлении, имеет смысл видеть изменения в файле.

Если вы используете обычный ввод-вывод (например, read), кто-то все еще может изменить файл во время его чтения. По-разному, копирование содержимого файла в буфер памяти не всегда в безопасности при наличии модификаций. Это «безопасно», поскольку read не будет разбиваться, но он не гарантирует, что ваши данные согласованы.
Если вы не используете readv, у вас нет никаких гарантий относительно атомарности (и даже с readv у вас нет гарантии, что то, что у вас есть в памяти, соответствует тому, что находится на диске, или что оно не меняется между двумя вызовами до readv). Кто-то может изменить файл между двумя операциями read или даже когда вы находитесь в середине его.
Этот не является только тем, что официально не гарантировано, но «возможно, все еще работает» - наоборот, например. под Linux пишет явно не атомный. Не случайно.

Хорошая новость:
Обычно процессы не просто открыть произвольную случайную файл и начать запись в него. Когда такое происходит, обычно это либо известный файл, который принадлежит процессу (например, файл журнала), либо файл, который явным образом сказал процессу для записи (например, сохранение в текстовом редакторе), или процесс создает новый файл (например,компилятор, создающий объектный файл), или только процесс добавляет в существующий файл (например, журналы db и, конечно, файлы журнала). Или процесс может заменить файл другим способом (или отменить связь).

В любом случае вся страшная проблема сводится к «нет проблемы», потому что либо вы хорошо знаете, что произойдет (так это ваша ответственность), либо она работает без помех.

Если вы действительно не нравится, вероятность того, что другой процесс может возможно писать в файл, а вы его на карту, вы можете просто опустить FILE_SHARE_WRITE под Windows, при создании дескриптора файла. POSIX делает его несколько более сложным, так как вам нужно указать fcntl дескриптор обязательной блокировки, который не обязательно поддерживается или 100% надежен для каждой системы (например, в Linux).

+0

Меня не интересует атомарность чтения или записи. Когда вы копируете содержимое файла в буфер памяти с помощью 'read', вы можете проверить вход чтения после этого, а затем убедитесь, что содержимое * в буфере * остается действительным. Когда входной файл отображается в память, он, как правило, обрабатывается как постоянный буфер после этого и получает доступ и анализируется непосредственно через обычные указатели. Если эта предположительно постоянная память изменяется внешним процессом, это нарушает ожидания компилятора и разработчика, что может привести к неопределенному поведению. –

+0

Правильно, если это проблема _really_, вы все равно можете сделать «memcpy» для анонимного сопоставления (или для блока, выделенного кучей). Конечно, вы теряете одно из главных преимуществ картографирования памяти: данные больше не доступны «магически» и «бесплатно». Однако я бы не стал копировать. Дело в том, что вы обычно знаете, когда вы изменяете файл (или программу от вашего имени), это происходит не случайно в случайных файлах. – Damon

+0

@Damon Это исходный файл. Люди открывают их в неожиданные моменты, и люди пишут их назад, когда вы меньше всего этого ожидаете. –

1

Теоретически, вы, вероятно, испытываете настоящую проблему, если кто-то делает , чтобы изменить файл во время его чтения. На практике: вы читаете символы , и ничего больше: никаких указателей или чего-либо еще , которые могут вызвать у вас неприятности. На практике ... формально, Я думаю, что это все еще неопределенное поведение, но это тот, который . Я не думаю, что вам нужно беспокоиться. Если модификации очень незначительны, вы получите много ошибок компилятора, но это о его конце.

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

И, наконец: система не будет произвольно открываться и изменить файл. Это исходный файл; это будет какой-то идиот , который делает это, и он заслуживает того, что получает. В случае без случае ваше неопределенное поведение приведет к повреждению системы или других файлов народов.

Обратите внимание, что большинство редакторов работают с частной копией; когда записывают назад, они делают это путем переименования оригинала и создания нового файла. В Unix, после того как вы открыли файл до mmap , все, что считается номером inode. И когда редактор переименовывает или удаляет файл, вы все равно сохраняете свою копию. Измененный файл получит новый индекс. Единственное, что вам нужно: беспокоиться о том, что кто-то открывает файл для обновления, а затем идет вокруг его модификации. Не так много программ делают это в текстовых файлах , за исключением добавления дополнительных данных в конец.

Так что формально, есть некоторый риск, я не думаю, что вам нужно беспокоиться об этом. (Если вы действительно параноик, вы можете отключить разрешение записи в то время как вы mmap ред. И если есть действительно вражеский агент, чтобы получить ваши, он может превратить его обратно на.)

+0

Я не думаю, что OP говорит о том, чтобы читать исходные файлы как таковые, только любой файл, который программа может читать во время выполнения. Таким образом, ваша точка зрения о ошибках компилятора выглядит неуместной. –

+0

@MarcClaesen Он упомянул разбор. Ошибки компилятора могут быть немного сильными, но в любое время, когда вы анализируете текст, вы должны каким-то образом обрабатывать ошибки ввода. –

Смежные вопросы