C Language
इंटरप्रोसेस कम्युनिकेशन (IPC)
खोज…
परिचय
अंतर-प्रक्रिया संचार (IPC) तंत्र विभिन्न स्वतंत्र प्रक्रियाओं को एक दूसरे के साथ संवाद करने की अनुमति देता है। मानक C कोई IPC तंत्र प्रदान नहीं करता है। इसलिए, ऐसे सभी तंत्र मेजबान ऑपरेटिंग सिस्टम द्वारा परिभाषित किए गए हैं। POSIX IPC तंत्र के एक व्यापक सेट को परिभाषित करता है; विंडोज एक और सेट को परिभाषित करता है; और अन्य सिस्टम अपने स्वयं के वेरिएंट को परिभाषित करते हैं।
सेमाफोर
सेमाफोर का उपयोग दो या अधिक प्रक्रियाओं के बीच संचालन को सिंक्रनाइज़ करने के लिए किया जाता है। POSIX अर्ध-कार्यों के दो अलग-अलग सेटों को परिभाषित करता है:
- - सिस्टम वी आईपीसी ’-
semctl()
,semop()
,semget()
। - 'POSIX Semaphores' -
sem_close()
,sem_destroy()
,sem_getvalue()
,sem_init()
,sem_open()
,sem_post()
,sem_trywait()
,sem_unlink()
।
यह खंड सिस्टम V IPC सेमाफोर का वर्णन करता है, इसलिए उन्हें यूनिक्स सिस्टम V से उत्पन्न किया जाता है।
सबसे पहले, आपको आवश्यक हेडर शामिल करना होगा। POSIX के पुराने संस्करणों की आवश्यकता है #include <sys/types.h>
; आधुनिक POSIX और अधिकांश प्रणालियों को इसकी आवश्यकता नहीं है।
#include <sys/sem.h>
फिर, आपको बच्चे के साथ-साथ माता-पिता दोनों में एक कुंजी को परिभाषित करने की आवश्यकता होगी।
#define KEY 0x1111
इस कुंजी को दोनों कार्यक्रमों में समान होना चाहिए या वे समान आईपीसी संरचना का उल्लेख नहीं करेंगे। इसके मूल्य को हार्ड-कोडिंग के बिना एक सहमत कुंजी उत्पन्न करने के तरीके हैं।
अगला, आपके कंपाइलर के आधार पर, आपको इस चरण को करने या करने की आवश्यकता नहीं हो सकती है: सेमाफोर संचालन के उद्देश्य के लिए एक संघ की घोषणा करें।
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
इसके बाद, अपनी कोशिश ( semwait
) को परिभाषित करें और बढ़ाएं ( semsignal
) संरचनाएं। P और V नाम डच से उत्पन्न हुए हैं
struct sembuf p = { 0, -1, SEM_UNDO}; # semwait
struct sembuf v = { 0, +1, SEM_UNDO}; # semsignal
अब, अपने आईपीसी सेमाफोर के लिए आईडी प्राप्त करके शुरू करें।
int id;
// 2nd argument is number of semaphores
// 3rd argument is the mode (IPC_CREAT creates the semaphore set if needed)
if ((id = semget(KEY, 1, 0666 | IPC_CREAT) < 0) {
/* error handling code */
}
माता-पिता में, 1 के काउंटर के लिए सेमाफोर को इनिशियलाइज़ करें।
union semun u;
u.val = 1;
if (semctl(id, 0, SETVAL, u) < 0) { // SETVAL is a macro to specify that you're setting the value of the semaphore to that specified by the union u
/* error handling code */
}
अब, आप जरूरत के अनुसार सेमाफोर को घटा या बढ़ा सकते हैं। अपने महत्वपूर्ण अनुभाग की शुरुआत में, आप semop()
फ़ंक्शन का उपयोग करके काउंटर को semop()
:
if (semop(id, &p, 1) < 0) {
/* error handling code */
}
सेमाफोर को बढ़ाने के लिए, आप &p
बजाय &v
उपयोग करते हैं:
if (semop(id, &v, 1) < 0) {
/* error handling code */
}
ध्यान दें कि प्रत्येक फ़ंक्शन सफलता पर 0
और विफलता पर -1
देता है। इन रिटर्न स्टेटस की जाँच नहीं करने से विनाशकारी समस्याएँ पैदा हो सकती हैं।
उदाहरण 1.1: थ्रेड्स के साथ रेसिंग
नीचे दिए गए कार्यक्रम में एक बच्चे के लिए एक प्रक्रिया fork
होगा और माता-पिता और बच्चे दोनों ही टर्मिनल पर वर्णों को किसी भी सिंक्रनाइज़ेशन के बिना मुद्रित करने का प्रयास करेंगे।
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main()
{
int pid;
pid = fork();
srand(pid);
if(pid < 0)
{
perror("fork"); exit(1);
}
else if(pid)
{
char *s = "abcdefgh";
int l = strlen(s);
for(int i = 0; i < l; ++i)
{
putchar(s[i]);
fflush(stdout);
sleep(rand() % 2);
putchar(s[i]);
fflush(stdout);
sleep(rand() % 2);
}
}
else
{
char *s = "ABCDEFGH";
int l = strlen(s);
for(int i = 0; i < l; ++i)
{
putchar(s[i]);
fflush(stdout);
sleep(rand() % 2);
putchar(s[i]);
fflush(stdout);
sleep(rand() % 2);
}
}
}
आउटपुट (पहला रन):
aAABaBCbCbDDcEEcddeFFGGHHeffgghh
(दूसरा रन):
aabbccAABddBCeeCffgDDghEEhFFGGHH
इस प्रोग्राम को कंपाइल करना और चलाना आपको हर बार एक अलग आउटपुट देना चाहिए।
उदाहरण 1.2: सेमीफोर के साथ रेसिंग से बचें
सेमाफोर का उपयोग करने के लिए उदाहरण 1.1 को संशोधित करना, हमारे पास है:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define KEY 0x1111
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
struct sembuf p = { 0, -1, SEM_UNDO};
struct sembuf v = { 0, +1, SEM_UNDO};
int main()
{
int id = semget(KEY, 1, 0666 | IPC_CREAT);
if(id < 0)
{
perror("semget"); exit(11);
}
union semun u;
u.val = 1;
if(semctl(id, 0, SETVAL, u) < 0)
{
perror("semctl"); exit(12);
}
int pid;
pid = fork();
srand(pid);
if(pid < 0)
{
perror("fork"); exit(1);
}
else if(pid)
{
char *s = "abcdefgh";
int l = strlen(s);
for(int i = 0; i < l; ++i)
{
if(semop(id, &p, 1) < 0)
{
perror("semop p"); exit(13);
}
putchar(s[i]);
fflush(stdout);
sleep(rand() % 2);
putchar(s[i]);
fflush(stdout);
if(semop(id, &v, 1) < 0)
{
perror("semop p"); exit(14);
}
sleep(rand() % 2);
}
}
else
{
char *s = "ABCDEFGH";
int l = strlen(s);
for(int i = 0; i < l; ++i)
{
if(semop(id, &p, 1) < 0)
{
perror("semop p"); exit(15);
}
putchar(s[i]);
fflush(stdout);
sleep(rand() % 2);
putchar(s[i]);
fflush(stdout);
if(semop(id, &v, 1) < 0)
{
perror("semop p"); exit(16);
}
sleep(rand() % 2);
}
}
}
आउटपुट:
aabbAABBCCccddeeDDffEEFFGGHHgghh
इस प्रोग्राम को कंपाइल करना और रन करना आपको हर बार एक ही आउटपुट देगा।