Memory Mapped IO
Memory Mapped IO işlemleriyle temel olarak,
read
,write
fonksiyonlarıyla yapılacak bir IO operasyonunun, ilgili sürecin adreslediği bellek alanı içerisinde doğrudan bellek erişim yöntemleriyle gerçeklenmesini sağlar.Birden fazla süreç, bir dosyayı kendi bellek alanlarına bu şekilde adreslediklerinde, aynı dosya üzerinde aynı anda bellek operasyonlarıyla işlem yapabilirler.
Eğer mapping işlemi, MAP_PRIVATE bayrağı ile oluşturulmuş ise, ilgili sürecin yaptığı değişiklikleri diğer süreçler göremezler. Bu şekildeki bir kullanım aynı zamanda, yapılan değişikliklerin dosyaya da tekrar yazılmayacağı anlamına gelmektedir.
MAP_SHARED bayrağı ile oluşturulmuş mapping'lerde ise, diğer süreçler de yapılan değişiklikleri görebilirler. Bu değişiklikler işletim sistemi tarafından dosyaya da yansıtılır.
mmap
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
mmap
sistem çağrısı ile ilgili sürecin adresleme aralığında yeni bir mapping oluşturulur.addr
alanı NULL ise sistem tarafından uygun bir adres otomatik olarak atanır.İşlemin başarılı olması durumunda, ilgili bellek adresi geri dönülür, diğer durumda MAP_FAILED makrosuyla test edebileceğimiz bir değer döner.
length
değeri mapping yapmak istediğimiz uzunluğu gösterir.prot
değeri ilgili alan üzerindeki erişim yetkilerini gösterir.PROT_NONE: ilgili alana erişim engellenir
PROT_READ: okunabilir
PROT_WRITE: yazılabilir
PROT_EXEC: kod çalıştırılabilir
Bu değerler veya operatörüyle birleştirilebilir.
flags
parametresi ile alanın kullanım şeklinde dair opsiyonlar belirtilir.MAP_PRIVATE olması durumunda, yapılan değişiklikler sadece mapping'i yapan süreç içerisinde görünebilir. Sistem bu noktada copy-on-write mekanizmasını kullanır ve değişiklik yapılmadığı müddetçe ek bir bellek kaybı söz konusu olmaz.
MAP_SHARED olması durumunda, yapılan değişiklikler aynı mapping işlemini yapmış diğer süreçlerde de görünür. Aynı zamanda sistem tarafından dosyaya da yansıtılır. Burada dosyaya yazma işlemini garanti etmek amacıyla
msync
sistem çağrısı da kullanılabilir.
Örnek: mmap kullanımı
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "../common/debug.h"
int main(int argc, char *argv[])
{
char *addr;
int fd;
struct stat sb;
if (argc != 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s file\n", argv[0]);
fd = open(argv[1], O_RDONLY);
if (fd == -1)
errExit("open");
/* Obtain the size of the file and use it to specify the size of
* the mapping and the size of the buffer to be written */
if (fstat(fd, &sb) == -1)
errExit("fstat");
addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED)
errExit("mmap");
if (write(STDOUT_FILENO, addr, sb.st_size) != sb.st_size)
fatal("partial/failed write");
exit(EXIT_SUCCESS);
}
munmap
mmap
işleminin tersini yaparak ilgili sürecin bellek alanındaki mapping'i kaldırır.Bellek üzerinde yapılan operasyonların dosya üzerinde de gerçekleştiğinden emin olmak için,
munmap
öncesindemsync
fonksiyonunu kullanmak gerekir.
Dosya Mapping İşlemleri
MAP_PRIVATE yöntemiyle dosyalar üzerinde mapping uygulamak, özellikle çalıştırılabilir dosyalar ve paylaşımlı kütüphane kullanımı için önemlidir.
Bu sayede aynı uygulamanın veya kütüphanenin text segmenti salt-okunur olarak açılabilir ve sistemdeki tüm süreçler tarafından ortak kullanılabilirken, data segmenti her süreç için özel olarak mapping yapıldığından, ilgili sürece ait değişiklikleri taşıyabilir.
MAP_SHARED yöntemiyle uygulanan mapping işlemlerinde ise tüm süreçler bellekteki aynı fiziksel alanı kullandığından önemli bir performans kazancı oluşur.
Memory Mapped IO Avantajları
read
,write
operasyonlarına yerine bellek üzerinde işlem yapmak, daha kolay okunur ve kısa kodlar üretebilmemizi sağlar.Tanımlanmış bir
struct
ile, bellek üzerinde geziniyormuş gibi işlemler yapılabilir. Özellikle rastgele erişimli dosyalarda ciddi bir kolaylık sağlanır.Bu yöntemle yapılan operasyonlar daha performanslı çalışır.
Normal
read
vewrite
işlemlerinde, sistemde 2 adet transfer işlemi oluşur. Bunlardan birincisi verinin dosyadan kernel içerisindeki tampon alanına taşınması, ikincisi ise tampon alandan ilgili userspace sürecin bellek alanına taşınması işlemidir.Memory mapped IO modelinde ikinci işleme gerek olmadığından, hem taşıma işleminden kurtulunur, hem de toplamda ihtiyaç duyulan bellek miktarı azalır. Özellikle birden fazla sürecin aynı (büyük) dosya üzerinde rastgele erişim yaptığı modelde önemli oranda avantaj sağlamaktadır.
Dezavantajlar
Küçük çaplı IO işlemlerinde, memory mapped IO yönteminin performansı daha düşük olacaktır.
Bunun temel nedeni, başlangıçta gereken ekstra mapping işlemi, page fault, unmap işlemleri vb.)
Bir diğer problem de bellek üzerinde yapılan işlemlerin dosyaya yansıtılmasını garanti etmek için ek işlem yapılma ihtiyacı olarak gösterilebilir.
Bu nedenlerle basit dosya işlemlerinde kullanımı genellikle önerilmez.