Быстрое изменение размера файла mmap

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

] Самый простой способ - использовать два сопоставления MAP_SHARED (увеличить файл, затем создать второе сопоставление, включающее увеличенную область) в одном и том же процессе над тем же файлом, а затем отменить сопоставление старого сопоставления после того, как все считыватели, которые могли получить к нему доступ, завершили работу. Однако мне любопытно, может ли приведенная ниже схема работать, и если да, то есть ли в ней какие-либо преимущества.

  1. mmap файл с MAP_PRIVATE
  2. делает доступ только для чтения к этой памяти в нескольких потоках
  3. либо получает мьютекс для файла, запись в память (предположим, что это сделано таким образом, что читатели, которые могут читать эту память, не испорчены этим)
  4. или получить мьютекс, но увеличить размер файл и используйте mremap, чтобы переместить его на новый адрес (измените размер сопоставления без копирования или ненужного ввода-вывода файла).

Сумасшедшая часть co mes in at (4). Если вы перемещаете память, старые адреса становятся недействительными, и читатели, которые все еще ее читают, могут внезапно получить нарушение доступа. Что, если мы модифицируем считыватели, чтобы перехватить это нарушение прав доступа, а затем перезапустить операцию (т.е. не перечитывать неверный адрес, повторно вычислять адрес с учетом смещения и нового базового адреса из mremap.) Да, я знаю, что это зло, но, на мой взгляд, читатели могут только успешно прочитать данные по старому адресу или выйти из строя с нарушением доступа и повторить попытку. Если приняты необходимые меры, то должно быть безопасным. Поскольку изменение размера будет происходить нечасто, считыватели в конечном итоге добьются успеха и не застрянут в цикле повторных попыток.

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

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

Я прав? Может это сработать? Есть ли у этого преимущества перед использованием двух сопоставлений MAP_SHARED?

9
задан Eloff 2 January 2012 в 17:58
поделиться