Bellek eşlemeli dosyalar
Belleğe eşlenen dosya, sanal bellekteki bir dosyanın içeriğini içerir. Bir dosya ve bellek alanı arasındaki bu eşleme, birden çok işlem de dahil olmak üzere bir uygulamanın doğrudan belleğe okuyup yazarak dosyayı değiştirmesine olanak tanır. Yönetilen kodu, bellekle eşlenen dosyalara yerel Windows işlevlerinin bellekle eşlenen dosyalara eriştikleri şekilde erişmek için Bellekle Eşlenen Dosyaları Yönetme bölümünde açıklandığı gibi kullanabilirsiniz.
İki tür belleğe eşlenmiş dosya vardır:
Kalıcı belleğe eşlenmiş dosyalar
Kalıcı dosyalar, disk üzerindeki bir kaynak dosyayla ilişkili belleğe eşlenmiş dosyalardır. Son işlem dosyayla çalışmayı bitirdiğinde, veriler disk üzerindeki kaynak dosyaya kaydedilir. Bu bellek eşlemeli dosyalar, son derece büyük kaynak dosyalarla çalışmak için uygundur.
Kalıcı olmayan bellek eşlemeli dosyalar
Kalıcı olmayan dosyalar, disk üzerindeki bir dosyayla ilişkilendirilmemiş bellekle eşlenen dosyalardır. Son işlem dosyayla çalışmayı bitirdiğinde, veriler kaybolur ve dosya çöp toplama tarafından geri kazanılır. Bu dosyalar, işlemler arası iletişimler (IPC) için paylaşılan bellek oluşturmak için uygundur.
İşlemler, Görünümler ve Belleği Yönetme
Bellekle eşlenen dosyalar birden çok işlem arasında paylaşılabilir. İşlemler, dosyayı oluşturan işlem tarafından atanan ortak bir ad kullanarak aynı bellek eşleme dosyasına eşlenebilir.
Bellekle eşlenen bir dosyayla çalışmak için, bellekle eşlenen dosyanın tamamının veya bir bölümünün görünümünü oluşturmanız gerekir. Ayrıca, bellekle eşlenen dosyanın aynı bölümünde birden çok görünüm oluşturabilir ve böylece eşzamanlı bellek oluşturabilirsiniz. İki görünümün eşzamanlı kalması için bunların aynı bellekle eşlenen dosyadan oluşturulması gerekir.
Dosya, bellek eşlemesi için kullanılabilir mantıksal bellek alanının boyutundan büyükse (32 bit bilgisayarda 2 GB) birden çok görünüm de gerekebilir.
İki tür görünüm vardır: akış erişim görünümü ve rastgele erişim görünümü. Bir dosyaya sıralı erişim için akış erişim görünümlerini kullanma; bu, kalıcı olmayan dosyalar ve IPC için önerilir. Kalıcı dosyalarla çalışmak için rastgele erişim görünümleri tercih edilir.
Belleğe eşlenen dosyalara işletim sisteminin bellek yöneticisi aracılığıyla erişilir, bu nedenle dosya otomatik olarak birkaç sayfaya bölümlenir ve gerektiğinde erişilir. Bellek yönetimini kendiniz işlemeniz gerekmez.
Aşağıdaki çizimde, birden çok işlemin aynı anda aynı bellekle eşlenen dosyaya nasıl birden çok ve çakışan görünüme sahip olabileceği gösterilmektedir.
Aşağıdaki görüntüde, bellekle eşlenmiş bir dosyaya birden çok ve çakışan görünüm gösterilir:
Bellek Eşlemeli Dosyalarla Programlama
Aşağıdaki tabloda, bellekle eşlenen dosya nesnelerini ve bunların üyelerini kullanmaya yönelik bir kılavuz sağlanır.
Görev | Kullanılacak yöntemler veya özellikler |
---|---|
Disk üzerindeki bir MemoryMappedFile dosyadan kalıcı belleğe eşlenmiş bir dosyayı temsil eden bir nesne elde etmek için. | MemoryMappedFile.CreateFromFile Yöntem. |
Kalıcı olmayan bellek eşlemeli bir MemoryMappedFile dosyayı (disk üzerindeki bir dosyayla ilişkilendirilmemiş) temsil eden bir nesne elde etmek için. | MemoryMappedFile.CreateNew Yöntem. - veya - MemoryMappedFile.CreateOrOpen Yöntem. |
Var olan bellekle eşlenmiş bir MemoryMappedFile dosyanın nesnesini almak için (kalıcı veya kalıcı değil). | MemoryMappedFile.OpenExisting Yöntem. |
Belleğe eşlenen dosyaya sıralı olarak erişilen bir görünüme yönelik bir nesne elde UnmanagedMemoryStream etmek için. | MemoryMappedFile.CreateViewStream Yöntem. |
Belleğe eşlenmiş bir UnmanagedMemoryAccessor dosyaya rastgele erişim görünümüne yönelik bir nesne elde etmek için. | MemoryMappedFile.CreateViewAccessor Yöntem. |
Yönetilmeyen kodla kullanılacak bir SafeMemoryMappedViewHandle nesne elde etmek için. | MemoryMappedFile.SafeMemoryMappedFileHandle Özellik. - veya - MemoryMappedViewAccessor.SafeMemoryMappedViewHandle Özellik. - veya - MemoryMappedViewStream.SafeMemoryMappedViewHandle Özellik. |
Bir görünüm oluşturulana kadar bellek ayırmayı geciktirmek için (yalnızca kalıcı olmayan dosyalar). (Geçerli sistem sayfa boyutunu belirlemek için özelliğini kullanın Environment.SystemPageSize .) |
CreateNew yöntemine MemoryMappedFileOptions.DelayAllocatePages tıklayın. - veya - CreateOrOpen parametre olarak bir MemoryMappedFileOptions numaralandırması olan yöntemler. |
Güvenlik
Bir numaralandırmayı parametre olarak alan MemoryMappedFileAccess aşağıdaki yöntemleri kullanarak bellekle eşlenmiş bir dosya oluşturduğunuzda erişim hakları uygulayabilirsiniz:
Parametre olarak alan MemoryMappedFileRights yöntemleri kullanarak OpenExisting mevcut bellek eşlemeli dosyayı açmak için erişim hakları belirtebilirsiniz.
Ayrıca, önceden tanımlanmış erişim kuralları içeren bir MemoryMappedFileSecurity nesne de ekleyebilirsiniz.
Bellekle eşlenen bir dosyaya yeni veya değiştirilmiş erişim kuralları uygulamak için yöntemini kullanın SetAccessControl . Mevcut bir dosyadan erişim veya denetim kuralları almak için yöntemini kullanın GetAccessControl .
Örnekler
Kalıcı Belleğe Eşlenmiş Dosyalar
Yöntemler, CreateFromFile diskte var olan bir dosyadan belleğe eşlenmiş bir dosya oluşturur.
Aşağıdaki örnek, son derece büyük bir dosyanın bir bölümünün belleğe eşlenmiş bir görünümünü oluşturur ve bir bölümünü işler.
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
class Program
{
static void Main(string[] args)
{
long offset = 0x10000000; // 256 megabytes
long length = 0x20000000; // 512 megabytes
// Create the memory-mapped file.
using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\ExtremelyLargeImage.data", FileMode.Open,"ImgA"))
{
// Create a random access view, from the 256th megabyte (the offset)
// to the 768th megabyte (the offset plus length).
using (var accessor = mmf.CreateViewAccessor(offset, length))
{
int colorSize = Marshal.SizeOf(typeof(MyColor));
MyColor color;
// Make changes to the view.
for (long i = 0; i < length; i += colorSize)
{
accessor.Read(i, out color);
color.Brighten(10);
accessor.Write(i, ref color);
}
}
}
}
}
public struct MyColor
{
public short Red;
public short Green;
public short Blue;
public short Alpha;
// Make the view brighter.
public void Brighten(short value)
{
Red = (short)Math.Min(short.MaxValue, (int)Red + value);
Green = (short)Math.Min(short.MaxValue, (int)Green + value);
Blue = (short)Math.Min(short.MaxValue, (int)Blue + value);
Alpha = (short)Math.Min(short.MaxValue, (int)Alpha + value);
}
}
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Runtime.InteropServices
Class Program
Sub Main()
Dim offset As Long = &H10000000 ' 256 megabytes
Dim length As Long = &H20000000 ' 512 megabytes
' Create the memory-mapped file.
Using mmf = MemoryMappedFile.CreateFromFile("c:\ExtremelyLargeImage.data", FileMode.Open, "ImgA")
' Create a random access view, from the 256th megabyte (the offset)
' to the 768th megabyte (the offset plus length).
Using accessor = mmf.CreateViewAccessor(offset, length)
Dim colorSize As Integer = Marshal.SizeOf(GetType(MyColor))
Dim color As MyColor
Dim i As Long = 0
' Make changes to the view.
Do While (i < length)
accessor.Read(i, color)
color.Brighten(10)
accessor.Write(i, color)
i += colorSize
Loop
End Using
End Using
End Sub
End Class
Public Structure MyColor
Public Red As Short
Public Green As Short
Public Blue As Short
Public Alpha As Short
' Make the view brighter.
Public Sub Brighten(ByVal value As Short)
Red = CType(Math.Min(Short.MaxValue, (CType(Red, Integer) + value)), Short)
Green = CType(Math.Min(Short.MaxValue, (CType(Green, Integer) + value)), Short)
Blue = CType(Math.Min(Short.MaxValue, (CType(Blue, Integer) + value)), Short)
Alpha = CType(Math.Min(Short.MaxValue, (CType(Alpha, Integer) + value)), Short)
End Sub
End Structure
Aşağıdaki örnek, başka bir işlem için aynı bellek eşlemeli dosyayı açar.
using System;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
class Program
{
static void Main(string[] args)
{
// Assumes another process has created the memory-mapped file.
using (var mmf = MemoryMappedFile.OpenExisting("ImgA"))
{
using (var accessor = mmf.CreateViewAccessor(4000000, 2000000))
{
int colorSize = Marshal.SizeOf(typeof(MyColor));
MyColor color;
// Make changes to the view.
for (long i = 0; i < 1500000; i += colorSize)
{
accessor.Read(i, out color);
color.Brighten(20);
accessor.Write(i, ref color);
}
}
}
}
}
public struct MyColor
{
public short Red;
public short Green;
public short Blue;
public short Alpha;
// Make the view brigher.
public void Brighten(short value)
{
Red = (short)Math.Min(short.MaxValue, (int)Red + value);
Green = (short)Math.Min(short.MaxValue, (int)Green + value);
Blue = (short)Math.Min(short.MaxValue, (int)Blue + value);
Alpha = (short)Math.Min(short.MaxValue, (int)Alpha + value);
}
}
Imports System.IO.MemoryMappedFiles
Imports System.Runtime.InteropServices
Class Program
Public Shared Sub Main(ByVal args As String())
' Assumes another process has created the memory-mapped file.
Using mmf = MemoryMappedFile.OpenExisting("ImgA")
Using accessor = mmf.CreateViewAccessor(4000000, 2000000)
Dim colorSize As Integer = Marshal.SizeOf(GetType(MyColor))
Dim color As MyColor
' Make changes to the view.
Dim i As Long = 0
While i < 1500000
accessor.Read(i, color)
color.Brighten(30)
accessor.Write(i, color)
i += colorSize
End While
End Using
End Using
End Sub
End Class
Public Structure MyColor
Public Red As Short
Public Green As Short
Public Blue As Short
Public Alpha As Short
' Make the view brigher.
Public Sub Brighten(ByVal value As Short)
Red = CShort(Math.Min(Short.MaxValue, CInt(Red) + value))
Green = CShort(Math.Min(Short.MaxValue, CInt(Green) + value))
Blue = CShort(Math.Min(Short.MaxValue, CInt(Blue) + value))
Alpha = CShort(Math.Min(Short.MaxValue, CInt(Alpha) + value))
End Sub
End Structure
Kalıcı Olmayan Belleğe Eşlenen Dosyalar
CreateNew ve CreateOrOpen yöntemleri, diskte var olan bir dosyaya eşlenmeyen bellekle eşlenmiş bir dosya oluşturur.
Aşağıdaki örnek, belleğe eşlenmiş bir dosyaya Boole değerleri yazan üç ayrı işlemden (konsol uygulamaları) oluşur. Aşağıdaki eylem dizisi gerçekleşir:
Process A
bellekle eşlenen dosyayı oluşturur ve dosyaya bir değer yazar.Process B
bellekle eşlenen dosyayı açar ve dosyaya bir değer yazar.Process C
bellekle eşlenen dosyayı açar ve dosyaya bir değer yazar.Process A
bellekle eşlenen dosyadaki değerleri okur ve görüntüler.Bellekle eşlenen dosyayla tamamlandıktan sonra
Process A
, dosya çöp toplama tarafından hemen geri kazanılır.
Bu örneği çalıştırmak için aşağıdakileri yapın:
Uygulamaları derleyin ve üç Komut İstemi penceresi açın.
İlk Komut İstemi penceresinde komutunu çalıştırın
Process A
.İkinci Komut İstemi penceresinde komutunu çalıştırın
Process B
.adresine
Process A
dönün ve ENTER tuşuna basın.Üçüncü Komut İstemi penceresinde komutunu çalıştırın
Process C
.adresine
Process A
dönün ve ENTER tuşuna basın.
çıktısı Process A
aşağıdaki gibidir:
Start Process B and press ENTER to continue.
Start Process C and press ENTER to continue.
Process A says: True
Process B says: False
Process C says: True
İşlem A
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Threading;
class Program
{
// Process A:
static void Main(string[] args)
{
using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 10000))
{
bool mutexCreated;
Mutex mutex = new Mutex(true, "testmapmutex", out mutexCreated);
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(1);
}
mutex.ReleaseMutex();
Console.WriteLine("Start Process B and press ENTER to continue.");
Console.ReadLine();
Console.WriteLine("Start Process C and press ENTER to continue.");
Console.ReadLine();
mutex.WaitOne();
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader reader = new BinaryReader(stream);
Console.WriteLine("Process A says: {0}", reader.ReadBoolean());
Console.WriteLine("Process B says: {0}", reader.ReadBoolean());
Console.WriteLine("Process C says: {0}", reader.ReadBoolean());
}
mutex.ReleaseMutex();
}
}
}
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Threading
Module Module1
' Process A:
Sub Main()
Using mmf As MemoryMappedFile = MemoryMappedFile.CreateNew("testmap", 10000)
Dim mutexCreated As Boolean
Dim mTex As Mutex = New Mutex(True, "testmapmutex", mutexCreated)
Using Stream As MemoryMappedViewStream = mmf.CreateViewStream()
Dim writer As BinaryWriter = New BinaryWriter(Stream)
writer.Write(1)
End Using
mTex.ReleaseMutex()
Console.WriteLine("Start Process B and press ENTER to continue.")
Console.ReadLine()
Console.WriteLine("Start Process C and press ENTER to continue.")
Console.ReadLine()
mTex.WaitOne()
Using Stream As MemoryMappedViewStream = mmf.CreateViewStream()
Dim reader As BinaryReader = New BinaryReader(Stream)
Console.WriteLine("Process A says: {0}", reader.ReadBoolean())
Console.WriteLine("Process B says: {0}", reader.ReadBoolean())
Console.WriteLine("Process C says: {0}", reader.ReadBoolean())
End Using
mTex.ReleaseMutex()
End Using
End Sub
End Module
İşlem B
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Threading;
class Program
{
// Process B:
static void Main(string[] args)
{
try
{
using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))
{
Mutex mutex = Mutex.OpenExisting("testmapmutex");
mutex.WaitOne();
using (MemoryMappedViewStream stream = mmf.CreateViewStream(1, 0))
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(0);
}
mutex.ReleaseMutex();
}
}
catch (FileNotFoundException)
{
Console.WriteLine("Memory-mapped file does not exist. Run Process A first.");
}
}
}
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Threading
Module Module1
' Process B:
Sub Main()
Try
Using mmf As MemoryMappedFile = MemoryMappedFile.OpenExisting("testmap")
Dim mTex As Mutex = Mutex.OpenExisting("testmapmutex")
mTex.WaitOne()
Using Stream As MemoryMappedViewStream = mmf.CreateViewStream(1, 0)
Dim writer As BinaryWriter = New BinaryWriter(Stream)
writer.Write(0)
End Using
mTex.ReleaseMutex()
End Using
Catch noFile As FileNotFoundException
Console.WriteLine("Memory-mapped file does not exist. Run Process A first." & vbCrLf & noFile.Message)
End Try
End Sub
End Module
İşlem C
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Threading;
class Program
{
// Process C:
static void Main(string[] args)
{
try
{
using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))
{
Mutex mutex = Mutex.OpenExisting("testmapmutex");
mutex.WaitOne();
using (MemoryMappedViewStream stream = mmf.CreateViewStream(2, 0))
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(1);
}
mutex.ReleaseMutex();
}
}
catch (FileNotFoundException)
{
Console.WriteLine("Memory-mapped file does not exist. Run Process A first, then B.");
}
}
}
Imports System.IO
Imports System.IO.MemoryMappedFiles
Imports System.Threading
Module Module1
' Process C:
Sub Main()
Try
Using mmf As MemoryMappedFile = MemoryMappedFile.OpenExisting("testmap")
Dim mTex As Mutex = Mutex.OpenExisting("testmapmutex")
mTex.WaitOne()
Using Stream As MemoryMappedViewStream = mmf.CreateViewStream(2, 0)
Dim writer As BinaryWriter = New BinaryWriter(Stream)
writer.Write(1)
End Using
mTex.ReleaseMutex()
End Using
Catch noFile As FileNotFoundException
Console.WriteLine("Memory-mapped file does not exist. Run Process A first, then B." & vbCrLf & noFile.Message)
End Try
End Sub
End Module