Странное поведение MemoryMappedFile
От: Codechanger Россия  
Дата: 17.01.11 08:09
Оценка:
Господа эксперты, поясните кто-нибудь следующий вопрос:

1. Создаем Persisted MemoryMappedFile длины 100 байт.
2. Вызываем у него CreateViewStream.
3. Смотрим длину полученного стрима, получаем 4096 байт.
Возникает вопрос — а как, собственно, определить реальную длину полученного потока?
Посмотрел рефлектором — данные 4096 байт выделяются, поле STATE структуры MEMORY_BASIC_INFORMATION имеет значение 0x2000,т.е. RESERVED.

Буду благодарен ответу на следующие вопросы:

1. Почему так получается.
2. Как получить реальную длину потока.

Заранее спасибо.

З.Ы. Саммоню в топик nikov, Jolly Roger и других экспертов
З.Ы.Ы. ViewStream создается с помошью CreateViewStream без параметров.
Re: Странное поведение MemoryMappedFile
От: Sinix  
Дата: 17.01.11 09:04
Оценка:
Здравствуйте, Codechanger, Вы писали:

C>Возникает вопрос — а как, собственно, определить реальную длину полученного потока?

Если коротко — практически никак, MMF заточен под fixed-size файлы и доступ в известных границах.
Самый простой способ — запоминать new FileInfo(filename).Length.

Я вас ещё больше обрадую. Угадайте, как себя ведёт код:
      string filename = @"d:\123.txt";
      File.WriteAllText(filename, "Hello!", Encoding.ASCII);

      long length = new FileInfo(filename).Length;

      using (MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(filename, FileMode.Open))
      {
        using (MemoryMappedViewStream stream = mmf.CreateViewStream())
        {
          stream.Position = 5; // 5000;
          byte[] bytes = Encoding.ASCII.GetBytes(", world!");
          stream.Write(bytes, 0, bytes.Length);
        }
      }

А при замене stream.Position = 5 на stream.Position = 5000?
Re[2]: Странное поведение MemoryMappedFile
От: Codechanger Россия  
Дата: 17.01.11 09:33
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Codechanger, Вы писали:


C>>Возникает вопрос — а как, собственно, определить реальную длину полученного потока?

S>Если коротко — практически никак, MMF заточен под fixed-size файлы и доступ в известных границах.
S>Самый простой способ — запоминать new FileInfo(filename).Length.

S>Я вас ещё больше обрадую. Угадайте, как себя ведёт код:

S>
S>      string filename = @"d:\123.txt";
S>      File.WriteAllText(filename, "Hello!", Encoding.ASCII);

S>      long length = new FileInfo(filename).Length;

S>      using (MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(filename, FileMode.Open))
S>      {
S>        using (MemoryMappedViewStream stream = mmf.CreateViewStream())
S>        {
S>          stream.Position = 5; // 5000;
S>          byte[] bytes = Encoding.ASCII.GetBytes(", world!");
S>          stream.Write(bytes, 0, bytes.Length);
S>        }
S>      }
S>

S>А при замене stream.Position = 5 на stream.Position = 5000?

Значит, придется где-то хранить ссылку на файл. Что тоже не очень хорошо, ибо неясно, в какой момент этот файл удалять. Этот GC такой GC...
Re[3]: Странное поведение MemoryMappedFile
От: Sinix  
Дата: 17.01.11 09:38
Оценка:
Здравствуйте, Codechanger, Вы писали:

C>Значит, придется где-то хранить ссылку на файл.

Зачем на файл, когда достаточно только длины?
Re[2]: Странное поведение MemoryMappedFile
От: AngeL B. Россия  
Дата: 17.01.11 12:13
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Я вас ещё больше обрадую. Угадайте, как себя ведёт код:

S>
S>      string filename = @"d:\123.txt";
S>      File.WriteAllText(filename, "Hello!", Encoding.ASCII);

S>      long length = new FileInfo(filename).Length;

S>      using (MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(filename, FileMode.Open))
S>      {
S>        using (MemoryMappedViewStream stream = mmf.CreateViewStream())
S>        {
S>          stream.Position = 5; // 5000;
S>          byte[] bytes = Encoding.ASCII.GetBytes(", world!");
S>          stream.Write(bytes, 0, bytes.Length);
S>        }
S>      }
S>

S>А при замене stream.Position = 5 на stream.Position = 5000?

Я не понимаю что именно вам не нравиться в поведении данного кода. Данные классы используют в своей работе функции API CreateFileMapping/MapViewOfFile которые используя виртуальную память могут кусать участки только кратные страницам вирт. памяти. Т.е. в данном случае 4096 байт.
Вы использовали самый простой конструктор без указания возможной "capacity" и класс подставил в функцию CreateFileMapping значение параметра "Размер-файла" = 0, что значит использовать "capacity" по длине файла (но кратно страницам). Т.е. в данном случае опять же 4096 байт. Соответсвенно в рамках 4Кбайт вы можете писать что хотите, за ними, — извините, но адресов не выделенно.
Используйте более сложный конструктор и можете там указывать "capacity" какой захотите.
Re[3]: Странное поведение MemoryMappedFile
От: Sinix  
Дата: 17.01.11 12:28
Оценка:
Здравствуйте, AngeL B., Вы писали:

AB>Я не понимаю что именно вам не нравиться в поведении данного кода.

Мне — всё нравится, это я топикстартера подбадриваю

А вот товарищей, привыкших исключительно к .NET-подходу "если я накосячу — фреймворк плюнет исключением", может неприятно обрадовать потеря 4095 бесценных байт. По-хорошему можно бы кидать ArgumentOutOfRangeException при попытки обращения за пределы реального размера файла, но один фиг mmf если и используются, то заворачиваются в какую-нибудь обёртку.
Re[4]: Странное поведение MemoryMappedFile
От: Codechanger Россия  
Дата: 17.01.11 12:43
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, AngeL B., Вы писали:


AB>>Я не понимаю что именно вам не нравиться в поведении данного кода.

S>Мне — всё нравится, это я топикстартера подбадриваю

S>А вот товарищей, привыкших исключительно к .NET-подходу "если я накосячу — фреймворк плюнет исключением", может неприятно обрадовать потеря 4095 бесценных байт. По-хорошему можно бы кидать ArgumentOutOfRangeException при попытки обращения за пределы реального размера файла, но один фиг mmf если и используются, то заворачиваются в какую-нибудь обёртку.


Ну вот написанием обертки сейчас и занимаюсь. Просветите, кто умный — non-persistent файлы целиком в памяти хранятся или все же на диске?
Re[5]: Странное поведение MemoryMappedFile
От: Sinix  
Дата: 17.01.11 12:58
Оценка:
Здравствуйте, Codechanger, Вы писали:

C>non-persistent файлы целиком в памяти хранятся или все же на диске?

В виртуальной памяти (могут быть спихнуты в своп).
http://msdn.microsoft.com/en-us/library/dd997372.aspx

Non-persisted memory-mapped files

Non-persisted files are memory-mapped files that are not associated with a file on a disk. When the last process has finished working with the file, the data is lost and the file is reclaimed by garbage collection. These files are suitable for creating shared memory for inter-process communications (IPC).


Более менее нормальное описание — тут:
http://msdn.microsoft.com/en-us/library/ms810613.aspx
Re[5]: Странное поведение MemoryMappedFile
От: AngeL B. Россия  
Дата: 17.01.11 14:02
Оценка:
Здравствуйте, Codechanger, Вы писали:

C>Ну вот написанием обертки сейчас и занимаюсь. Просветите, кто умный — non-persistent файлы целиком в памяти хранятся или все же на диске?


Данные non-persistent файлов храняться в свопе. Возможно полностью, возможно частично, возможно никогда туда не попадают, что зависит от количества свободной оперативки, состояния системы и контролироваться никак не может, т.к. относится к механизму страничного свопинга.
Более подробно читай у Sinix-а по ссылке в параллельном ответе.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.