13 Şubat 2017 Pazartesi

Shared Memory

Posix
Posix ile shared memory kullanmak için yapılması gereken adımlar şöyle.
1. shm_open ile bir bellek yaratılır.
2. ftruncate ile bellek boyutu ayarlanır.
3. mmap ile bellek kendi uygulamamıza dahil edilir.
4. Interprocess mutex ile bellek korunarak sprintf türünden bir metod ile yazma ve okuma işlemi yapılır.

include dosyaları
Metodları kullanabilmek için şu dosyaları dahil etmek gerekiyor.
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/mman.h>
shm_open ve /dev/shm ilişkisi
shm_open() /dev/shm dizini altında bir dosya yaratıyor. Bu dosyanın nereye mount edildiğini görmek için aşağıdaki gibi yapılabilir:
mount | grep shm
Komutun sonucunda şuna benzer bir şey görürüz
tmpfs on /dev/shm type tmpfs (rw)
shm_open
shm_open ile verilen shared memory ismi "/filename" kalıbına uymalı.
shm_open bir file descriptor dönüyor. Ancak fd'yi mmap ile kendi sayfamıza almadan kullanmak bir hata.
If fildes refers to a shared memory object, the result of the  write() function is unspecified.
Basit bir örnek
const char *name = "SHARON";
int  shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
shm_unlink
Dosyayı kapatır. file descriptor değil dosya ismi aldığına dikkat etmek lazım.
const char *name = "OS";
shm_fd = shm_open(name, O_RDONLY, 0666);
...
shm_unlink(name);
ftruncate
Bu metod master uygulama tarafından çağırılır. shm_open ile açılan dosya'nın boyunu ayarlamayı sağlar. Mutlaka yapılması gerekir. Örnek:
const int SIZE = 4096;
const char *name = "OS";

int shm_fd;
void *ptr;

shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, SIZE);
ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
mmap
Hem master hem de child uygulama tarafından yapılması gerekir. Bu çağrı neticesinde, yaratılan shared memory alanını, kendi uygulamamızda kullanabiliriz. ftruncate çağrısında verilen dosya boyunun aynısını veya daha küçük bir değeri kullanmak gerekir.
mmap yazısına taşıdım

Master Uygulama Örneği
//create shared memory
int shmem_fd = shm_open("/my_shmem",
                                         O_CREAT | O_RDWR, //Yarat ve okuma yazma hakkı al
                                         S_IRUSR | S_IWUSR
                                       );
//truncate memory object
ftruncate(shmem_fd, object_size)
//map shared memory to this process
void *addr = mmap(NULL,
                              object_size,
                              PROT_READ | PROT_WRITE, //Okuma ve yazma hakkı
                              MAP_SHARED, //IPC yapmak istiyoruz
                              shmem_fd,
                              0
                              );
Child Uygulama Örneği
int shmem_fd = shm_open("/my_shmem",
                                         O_RDWR, //Okuma yazma hakkı al
                                         0
                                        );
//map shared memory to this process
void *addr = mmap(NULL,
                              object_size,
                              PROT_READ | PROT_WRITE, //Okuma ve yazma hakkı
                              MAP_SHARED, //IPC yapmak istiyoruz
                              shmem_fd,
                              0
                              );
mmap ve sayfa hizalaması (page alignment)
Bu kısım sadece teorik bilgi. mmap işletim sisteminin sayfaları üzerinde çalıştığı için istenilen hafıza miktarı otomatik olarak sayfa büyüklüğüne göre ayarlanır. Yani bazen istenilenden biraz daha fazla alan kullanılır.

mmap ve lazy initialization
Bu kısım da sadece teorik bilgi. mmap istenilen bellek büyüklüğünü sayfalara dokundukça ayırıyor denilmiş. Yani 4 GB'lik bellek alanı gerektikçe veriliyor.

boost
boost ile shared memory kullanmak için şu adımlar izlenmeli.
1. Önce bir shared memory alanı yaratılmalı. Bu alan bir boost::interprocess::allocator'a verilmeli.
2. boost::interprocess container yukarıda yaratılan allocator ile belleğe erişir.
3. Diğer uygulamalar ile eşzamanlılığı sağlamak için bir interprocess mutex kullanılmalı.

QT
//Master uygulama için
QSharedMemory sharedMemory(QString("Shared Memory"));//key is Shared Memory
sharedMemory.create(42);//42 byte size

//Slave uygulama için
QSharedMemory sharedMemory(QString("Shared Memory"));//key is Shared Memory
sharedMemory.attach(QSharedMemory::ReadOnly);
Aşağıda create ve attach metodlarının kodları var.


Hiç yorum yok:

Yorum Gönder