Pemetaan Memori

Panggilan sistem mmap () menyediakan pemetaan di ruang alamat virtual dari proses panggilan yang memetakan file atau perangkat ke dalam memori. Ini dari dua jenis -

File mapping or File-backed mapping- Pemetaan ini memetakan area memori virtual proses ke file. Ini berarti membaca atau menulis ke area memori tersebut menyebabkan file dibaca atau ditulis. Ini adalah jenis pemetaan default.

Anonymous mapping- Pemetaan ini memetakan area memori virtual proses tanpa didukung oleh file apa pun. Isi diinisialisasi ke nol. Pemetaan ini mirip dengan alokasi memori dinamis (malloc ()) dan digunakan dalam beberapa implementasi malloc () untuk alokasi tertentu.

Memori dalam satu pemetaan proses dapat digunakan bersama dengan pemetaan di proses lain. Ini dapat dilakukan dengan dua cara -

  • Ketika dua proses memetakan wilayah yang sama dari sebuah file, mereka berbagi halaman memori fisik yang sama.

  • Jika proses anak dibuat, itu mewarisi pemetaan induk dan pemetaan ini merujuk ke halaman memori fisik yang sama seperti yang dimiliki induk. Jika ada perubahan data dalam proses anak, halaman berbeda akan dibuat untuk proses anak.

Ketika dua atau lebih proses berbagi halaman yang sama, setiap proses dapat melihat perubahan konten halaman yang dibuat oleh proses lain tergantung pada jenis pemetaan. Jenis pemetaan bisa pribadi atau bersama -

Private Mapping (MAP_PRIVATE) - Modifikasi pada konten pemetaan ini tidak terlihat oleh proses lain dan pemetaan tidak dilakukan ke file yang mendasarinya.

Shared Mapping (MAP_SHARED) - Modifikasi pada konten pemetaan ini terlihat oleh proses lain dan pemetaan dilakukan ke file yang mendasarinya.

#include <sys/mman.h>

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

Panggilan sistem di atas mengembalikan alamat awal pemetaan pada keberhasilan atau MAP_FAILED pada kesalahan.

Alamat virtual addr, dapat ditentukan oleh pengguna atau dibuat oleh kernel (setelah memasukkan addr sebagai NULL). Panjang bidang yang ditunjukkan membutuhkan ukuran pemetaan dalam byte. Prot bidang menunjukkan nilai perlindungan memori seperti PROT_NONE, PROT_READ, PROT_WRITE, PROT_EXEC yang dimaksudkan untuk wilayah yang tidak dapat diakses, dibaca, ditulis atau dijalankan secara berurutan. Nilai ini bisa tunggal (PROT_NONE) atau bisa ORd dengan salah satu dari tiga bendera (3 terakhir). Bendera bidang menunjukkan jenis pemetaan, baik MAP_PRIVATE atau MAP_SHARED. Kolom 'fd' menunjukkan deskriptor file yang mengidentifikasi file yang akan dipetakan dan kolom 'offset' menyiratkan titik awal file, jika perlu memetakan seluruh file, offset harus nol.

#include <sys/mman.h>

int munmap(void *addr, size_t length);

Panggilan sistem di atas mengembalikan 0 jika berhasil atau -1 saat error.

Sistem memanggil munmap, melakukan unmapping wilayah yang sudah dipetakan memori. Addr field menunjukkan alamat awal pemetaan dan panjangnya menunjukkan ukuran dalam byte dari pemetaan yang akan dibuka. Biasanya pemetaan dan unmapping untuk seluruh wilayah yang dipetakan. Jika ini harus berbeda, maka harus dikecilkan atau dipotong menjadi dua bagian. Jika addr tidak memiliki pemetaan, panggilan ini tidak akan berpengaruh dan panggilan kembali 0 (berhasil).

Mari kita pertimbangkan contoh -

Step 1 - Tuliskan karakter Alpha Numeric kedalam file seperti gambar dibawah -

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- Petakan konten file ke dalam memori menggunakan panggilan sistem mmap (). Ini akan mengembalikan alamat awal setelah dipetakan ke dalam memori.

Step 3- Akses konten file menggunakan notasi array (juga dapat diakses dengan notasi pointer) karena tidak membaca panggilan sistem read () yang mahal. Dengan menggunakan pemetaan memori, hindari banyak penyalinan antara ruang pengguna, buffer ruang kernel, dan cache buffer.

Step 4 - Ulangi membaca konten file sampai pengguna memasukkan "-1" (menandakan akhir akses).

Step 5 - Lakukan kegiatan pembersihan yaitu membuka peta wilayah memori yang dipetakan (munmap ()), menutup file dan menghapus file.

/* 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;
}

Keluaran

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