Bellek Eşleme

Mmap () sistem çağrısı, dosyaları veya aygıtları belleğe eşleyen çağrı işleminin sanal adres alanında eşleştirme sağlar. Bu iki çeşittir -

File mapping or File-backed mapping- Bu eşleme, işlemin sanal belleğinin alanını dosyalara eşler. Bu, belleğin bu alanlarına okuma veya yazma, dosyanın okunmasına veya yazılmasına neden olduğu anlamına gelir. Bu, varsayılan eşleme türüdür.

Anonymous mapping- Bu eşleme, herhangi bir dosya tarafından desteklenmeden işlemin sanal belleğinin alanını eşler. İçerikler sıfır olarak başlatılır. Bu eşleme, dinamik bellek tahsisine (malloc ()) benzer ve belirli tahsisler için bazı malloc () uygulamalarında kullanılır.

Bir işlem eşlemesindeki bellek, diğer işlemlerdeki eşlemelerle paylaşılabilir. Bu iki şekilde yapılabilir -

  • İki işlem bir dosyanın aynı bölgesini eşlediğinde, aynı fiziksel bellek sayfalarını paylaşırlar.

  • Bir alt süreç oluşturulursa, üst süreç eşlemelerini devralır ve bu eşlemeler, üst süreç ile aynı fiziksel bellek sayfalarına başvurur. Alt süreçteki herhangi bir veri değişikliği durumunda, alt süreç için farklı sayfalar oluşturulur.

İki veya daha fazla işlem aynı sayfaları paylaştığında, her işlem, eşleme türüne bağlı olarak diğer işlemler tarafından yapılan sayfa içeriklerinde yapılan değişiklikleri görebilir. Eşleme türü özel veya paylaşımlı olabilir -

Private Mapping (MAP_PRIVATE) - Bu eşlemenin içeriğinde yapılan değişiklikler diğer işlemler tarafından görülemez ve eşleme, temel alınan dosyaya taşınmaz.

Shared Mapping (MAP_SHARED) - Bu eşlemenin içeriğinde yapılan değişiklikler diğer işlemler tarafından görülebilir ve eşleme, temel alınan dosyaya taşınır.

#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

Yukarıdaki sistem çağrısı, başarılı olduğunda eşlemenin başlangıç ​​adresini veya hata durumunda MAP_FAILED'i döndürür.

Sanal adres adres, kullanıcı tarafından belirtilebilir veya çekirdek tarafından oluşturulabilir (adres NULL olarak geçtikten sonra). Belirtilen alan uzunluğu, bayt cinsinden eşleme boyutunu gerektirir. Koruma alanı, sırasıyla erişilemeyen, okunamayan, yazılamayan veya yürütülemeyen bölgeler için PROT_NONE, PROT_READ, PROT_WRITE, PROT_EXEC gibi bellek koruma değerlerini gösterir. Bu değer tek olabilir (PROT_NONE) veya üç işaretten herhangi biriyle ORd olabilir (son 3). Alan bayrakları, eşleme türünü veya MAP_PRIVATE veya MAP_SHARED'i gösterir. 'Fd' alanı, eşlenecek dosyayı tanımlayan dosya tanımlayıcısını belirtir ve 'offset' alanı dosyanın başlangıç ​​noktasını belirtir, tüm dosyayı eşlemek gerekirse, uzaklık sıfır olmalıdır.

#include <sys/mman.h>

int munmap(void *addr, size_t length);

Yukarıdaki sistem çağrısı başarı durumunda 0 veya hata durumunda -1 döndürür.

Sistem çağrısı munmap, halihazırda bellek eşlemeli bölgenin eşlemesini kaldırır. Adres alanları, eşlemenin başlangıç ​​adresini belirtir ve uzunluk, eşleştirilmeyecek eşlemenin bayt cinsinden boyutunu belirtir. Genellikle, eşleme ve eşleme kaldırma, eşlenen bölgelerin tamamı için olacaktır. Bunun farklı olması gerekiyorsa, ya küçültülmeli ya da iki parça halinde kesilmelidir. Adresin herhangi bir eşlemesi yoksa, bu çağrının hiçbir etkisi olmaz ve çağrı 0 (başarılı) döndürür.

Bir örnek ele alalım -

Step 1 - Aşağıda gösterildiği gibi dosyaya Alfa Sayısal karakterleri yazın -

0 1 2 25 26 27 28 29 30 31 32 33 34 35 36 37 38 59 60 61
A B C Z 0 1 2 3 4 5 6 7 8 9 A b c x y z

Step 2- Dosya içeriğini mmap () sistem çağrısını kullanarak belleğe eşleyin. Bu, belleğe eşlendikten sonra başlangıç ​​adresini döndürecektir.

Step 3- Pahalı read () sistem çağrısını okumadığı için dizi gösterimini kullanarak dosya içeriğine erişin (işaretçi gösterimiyle de erişebilir). Bellek eşlemeyi kullanarak, kullanıcı alanı, çekirdek alanı arabellekleri ve arabellek önbelleği arasında birden çok kopyalama yapmaktan kaçının.

Step 4 - Kullanıcı “-1” girene kadar dosya içeriğini okumayı tekrarlayın (erişimin sonunu belirtir).

Step 5 - Temizleme etkinliklerini gerçekleştirin, yani eşlenen bellek bölgesini (munmap ()) eşleştirin, dosyayı kapatın ve dosyayı kaldırın.

/* Filename: mmap_test.c */
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
void write_mmap_sample_data();

int main() {
   struct stat mmapstat;
   char *data;
   int minbyteindex;
   int maxbyteindex;
   int offset;
   int fd;
   int unmapstatus;
   write_mmap_sample_data();
   if (stat("MMAP_DATA.txt", &mmapstat) == -1) {
      perror("stat failure");
      return 1;
   }
   
   if ((fd = open("MMAP_DATA.txt", O_RDONLY)) == -1) {
      perror("open failure");
      return 1;
   }
   data = mmap((caddr_t)0, mmapstat.st_size, PROT_READ, MAP_SHARED, fd, 0);
   
   if (data == (caddr_t)(-1)) {
      perror("mmap failure");
      return 1;
   }
   minbyteindex = 0;
   maxbyteindex = mmapstat.st_size - 1;
   
   do {
      printf("Enter -1 to quit or ");
      printf("enter a number between %d and %d: ", minbyteindex, maxbyteindex);
      scanf("%d",&offset);
      if ( (offset >= 0) && (offset <= maxbyteindex) )
      printf("Received char at %d is %c\n", offset, data[offset]);
      else if (offset != -1)
      printf("Received invalid index %d\n", offset);
   } while (offset != -1);
   unmapstatus = munmap(data, mmapstat.st_size);
   
   if (unmapstatus == -1) {
      perror("munmap failure");
      return 1;
   }
   close(fd);
   system("rm -f MMAP_DATA.txt");
   return 0;
}

void write_mmap_sample_data() {
   int fd;
   char ch;
   struct stat textfilestat;
   fd = open("MMAP_DATA.txt", O_CREAT|O_TRUNC|O_WRONLY, 0666);
   if (fd == -1) {
      perror("File open error ");
      return;
   }
   // Write A to Z
   ch = 'A';
   
   while (ch <= 'Z') {
      write(fd, &ch, sizeof(ch));
      ch++;
   }
   // Write 0 to 9
   ch = '0';
   
   while (ch <= '9') {
      write(fd, &ch, sizeof(ch));
      ch++;
   }
   // Write a to z
   ch = 'a';
   
   while (ch <= 'z') {
      write(fd, &ch, sizeof(ch));
      ch++;
   }
   close(fd);
   return;
}

Çıktı

Enter -1 to quit or enter a number between 0 and 61: 3 
Received char at 3 is D 
Enter -1 to quit or enter a number between 0 and 61: 28
Received char at 28 is 2 
Enter -1 to quit or enter a number between 0 and 61: 38 
Received char at 38 is c 
Enter -1 to quit or enter a number between 0 and 61: 59 
Received char at 59 is x 
Enter -1 to quit or enter a number between 0 and 61: 65 
Received invalid index 65 
Enter -1 to quit or enter a number between 0 and 61: -99 
Received invalid index -99 
Enter -1 to quit or enter a number between 0 and 61: -1