Shared Memory in C

Shared Memory কি ও কেন?

সাধারণভাবে দু’টি আলাদা Application কোন কমন মেমরি এক্সেস করতে পারে না। আবার কখনো এমন হতে পারে যে, একই প্রোগ্রামের দু’টি আলাদা প্রসেসকে একটি গ্লোবাল ভ্যারিয়েবলের ভ্যালুর উপর ডিসিশন নিতে হতে পারে। আপাতত ধরি, একটি প্রসেসে কোন ভ্যারিয়েবলে write করলাম, আরেকটি প্রসেসে ঐ ভ্যারিয়েবল থেকেই read করলাম। সাধারণভাবে এই সিম্পল কাজটাও আমরা করতে পারি না। কারণ, প্রত্যেক process এর আলাদা address space আছে। তাই even একই প্রোগ্রাম হলেও আমরা একই ভ্যারিয়েবলের এক প্রসেসে চেইঞ্জ করা ভ্যালু অন্য প্রসেসে পাই না।

এখানেই আসছে Shared Memory। Shared Memory নামটা দেখেই বুঝা যাচ্ছে, এটা আসলে কি করে। হ্যা, Shared Memory হচ্ছে একটা “Segment of Memory” যেটা একাধিক প্রসেস শেয়ার করতে পারে। তার মানে একটা প্রসেস থেকে কোন Shared Variable এর ভ্যালু চেইঞ্জ হলে যে যে প্রসেসে ঐ ভ্যারিয়েবল Share করা হয়েছে, তারা প্রত্যেকেই ঐ আপডেটেড ভ্যালু পাবে।

Implementation:

আপাতত আমরা দু’টি প্রোগ্রাম থেকে সেইম ভ্যারিয়েবল এ ভ্যালু write আর read করে দেখব। Shared Memory ইউজ করার আগে কয়েকটি সিস্টেম কল দিতে হয়ঃ

  • ftok(): এটা কল দিতে হয় একটা unique key বানাতে।
  • shmget(): যে Shared Memory Segment টা আমি access করতে চাচ্ছি, সেটা পাওয়ার জন্য এই ফাংশন কল দিতে হয়।
  • shmat(): কোড যে প্রসেসে আছে, সেটাকে Shared Memory Segment এর সাথে attach করে।
  • shmdt(): Shared Memory Segment কে প্রসেস থেকে detach করে।
  • shmctl(): Shared Memory Segment টিকে destroy করার জন্য কল করা হয়।

আমরা যদি অন্য কোনভাবে unique key টা বানাতে পারি, তাহলে ftok() আর কল করা লাগবে না। তবে মনে রাখতে হবে, এই key টা প্রত্যেক মেমরি সেগমেন্টের জন্য ইউনিক হতে হবে।

read প্রসেস আর write প্রসেস দু’টির জন্যই shmget() ফাংশনটি ব্যবহার করতে হবে। যখন read করব তখন তো already Shared Memory Segment টি অন্য প্রসেস ক্রিয়েট করে ফেলেছে, তাই read প্রসেসে shmget() কল করা হয় ঐ ক্রিয়েটেড Shared Memory Segment টি পাওয়ার জন্য। এই কাজটি করা হয় shmget() কল করার সময় তৃতীয় প্যারামিটার (int shmflg) টি শূণ্য পাঠিয়ে। তখন সিস্টেম বুঝে নেয় এবার shmget() কল করা হয়েছে আগের কোন ক্রিয়েটেড Shared Memory Segment এক্সেস করার জন্য। ডিটেইলস shmget() এর উপরের লিঙ্কে গেলেই পাওয়া যাবে।

get করলাম, এবার Shared Memory Segment টি attach করব রানিং প্রসেসের সাথে। এই জন্য কল দিতে হবে shmat()।

এখন নরমালি যেভাবে পয়েন্টার ভ্যারিয়েবল ইউজ করি, সেভাবেই দুই প্রসেসেই ইউজ করব।

আমি দু’টি আলাদা প্রোগ্রাম থেকে একই ভ্যারিয়েবল এক্সেস করার কোড এখানে দিচ্ছি। এক প্রোগ্রাম থেকে ভ্যালু পুশ করব, আরেক প্রোগ্রাম থেকে ঐ ভ্যারিয়েবলের ভ্যালু এক্সেস করব।

ভ্যারিয়েবলে ভ্যালু write করার কোডঃ write.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <unistd.h>

int main() {

	key_t sharedKey;
	int shmId, *sharedVariable;
	char path[100], command[100];
	snprintf(path, sizeof(path), "/rnd/sharedMemory/sharedKey.txt");

	snprintf(command, sizeof(command), "touch /rnd/sharedMemory/sharedKey.txt");
	system(command);

	sharedKey = ftok(path, 'm');
	if (sharedKey == -1) {

		perror("Shared Key Generation: ");
		return 0;
	}
	
	shmId = shmget(sharedKey, sizeof(int), 0666 | IPC_CREAT);
	if (shmId == -1) {

		perror("Shared Memory ID: ");
		printf("%s %d\n", strerror(errno), errno);
		return 0;
	}
	else if (shmId >= 0) {

		snprintf(command, sizeof(command), "echo \"%d\">>shmid.txt", shmId);
		system(command);
	}

	sharedVariable = (int *)shmat(shmId, NULL, 0);
	if (sharedVariable < 0) {

		perror("Shared Value Memory Attachment: ");
		return 0;
	}
	*sharedVariable = 2;
	printf("Data Written in memory: %d\n", *sharedVariable);
	shmdt(sharedVariable);
	return 0;
}

ভ্যারিয়েবল থেকে ভ্যালু read করার কোডঃ read.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>

int main() {

    key_t sharedKey1;
    int shmId, *sharedVariable;
    char path[100];
    snprintf(path, sizeof(path), "/rnd/sharedMemory/sharedKey.txt");

    sharedKey1 = ftok(path, 'm');
    if (sharedKey1 == -1) {

         perror("Shared Key Generation: ");
         return 0;
    }

    shmId = shmget(sharedKey1, sizeof(int), 0);
    if (shmId == -1) {

        perror("Shared Memory ID: ");
        printf("%s %d\n", strerror(errno), errno);
        return 0;
    }

    sharedVariable = (int *) shmat(shmId, (void*)0, 0);
    if (sharedVariable < 0) {

        perror("Shared Value Memory Attachment: ");
        return 0;
    }

    printf("Data read from memory: %d\n", *sharedVariable);

    shmdt(sharedVariable);
    shmctl(shmId,IPC_RMID,NULL);
    return 0;
}

এখন write.c কোডটি রান করার পর read.c কোডটি রান করলে দেখা যাবে, যদিও read.c এর কোথাও sharedVariable ভ্যারিয়েবলটিতে ভ্যালু assign করা হয়নি, তাও ভ্যারিয়েবলটি write.c তে assign করা ভ্যালুটিই পাচ্ছে। আর এভাবেই inter process communication (ipc) এর মাধ্যমে এক প্রসেস করা যেকোন চেইঞ্জ আরেক প্রসেস থেকে পেতে পারি।

Tagged

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s