2011-04-12 8 views
6

से अन्य धागे आईपीसी संदेश पकड़ता है जब मेरे पास लिनक्स पर दो अलग-अलग आईपीसी संदेश कतार हैं, कभी-कभी गलत कतार के संदेश पकड़े जाते हैं।धागा कतार (लिनक्स)

निम्नलिखित खिलौना प्रोग्राम समस्या प्रदर्शित करता है, विभिन्न प्रोसेसर पर दोहराया जा सकता है।

किसी भी मदद की बहुत सराहना की!

बर्ट

/* 
    To compile; 
    gcc MM.c -o mm -fno-stack-protector -pthread 

    We want Mickey to send a message to Minnie exclusively. 
    We want Donald to send a message to pluto exclusively. 

    Problem: Pluto intercepts Minnie's messages. 

    Listing gives: 

    $ ./mm 
    Mickey thread successfully started. 
    Minnie thread successfully started. 
    Pluto thread successfully started. 
    Donald thread successfully started. 
    Donald sent a message to Pluto. 
    Mickey sent a message to Minnie. 
    Pluto received: Sit, Pluto! 

    Minnie received: Hello, Minnie! 

    Mickey sent a message to Minnie. (100 times) 

    Pluto received: Hello, Minnie! 
*/ 
#include <sys/types.h> 
#include <sys/msg.h> 
#include <sys/ipc.h> 
#include <string.h> 
#include <stdio.h> 

pthread_t t1,t2,t3,t4; 

// Mickey send 
key_t ipcMickey; 
int mqMickeyid; 
char helloMickeymsg[] = {"Hello, Minnie!"}; 
struct { long type; char text[100]; } myMickeymsg; 

// Minnie get 
int mqMinnieid; 
struct { long type; char text[100]; } myMinniemsg; 

// Donald send 
key_t ipcDonald; 
int mqDonaldid; 
char helloDonaldmsg[] = {"Sit, Pluto!"}; 
struct { long type; char text[100]; } myDonaldmsg; 

// Pluto get 
int mqPlutoid; 
struct { long type; char text[100]; } myPlutomsg; 

static void * DONALDthreadFunc(void *arg) 
{ 
    printf("Donald thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //send 
     memset(myDonaldmsg.text, 0, 100); 
     strncpy(myDonaldmsg.text, helloDonaldmsg, strlen(helloDonaldmsg)); 
     myDonaldmsg.type = 1; 
     msgsnd(mqDonaldid, &myDonaldmsg, sizeof(myDonaldmsg), 0); 
     printf("Donald sent a message to Pluto.\r\n"); 
     sleep(4); 
    } 

    /* just a formality */ 
    return (void *) strlen(s); 
} 

static void * PLUTOthreadFunc(void *arg) 
{ 
    printf("Pluto thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //receive 
     mqPlutoid = msgget(ipcDonald, 0); 
     msgrcv(mqPlutoid, &myPlutomsg, sizeof(myPlutomsg), 0, 0); 
     printf("Pluto received: %s\r\n\r\n", myPlutomsg.text); 
     sleep(1); 
    } 

    /* just a formality */ 
    return (void *) strlen(s); 
} 

static void * MICKEYthreadFunc(void *arg) 
{ 
    printf("Mickey thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //send 
     memset(myMickeymsg.text, 0, 100); 
     strncpy(myMickeymsg.text, helloMickeymsg, strlen(helloMickeymsg)); 
     myMickeymsg.type = 1; 
     msgsnd(mqMickeyid, &myMickeymsg, sizeof(myMickeymsg), 0); 
     printf("Mickey sent a message to Minnie.\r\n"); 
     usleep(10000); 
    } 

    /* just a formality */ 
    return (void *) strlen(s); 
} 

static void * MINNIEthreadFunc(void *arg) 
{ 
    printf("Minnie thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //receive 
     mqMinnieid = msgget(ipcMickey, 0); 
     msgrcv(mqMinnieid, &myMinniemsg, sizeof(myMinniemsg), 0, 0); 
     printf("Minnie received: %s\r\n\r\n", myMinniemsg.text); 
     sleep(3); 
    } 

    return (void *) strlen(s); 
} 

int main (void) 
{ 
     ipcMickey = ftok("/tmp/mqmickey", 63); 
     mqMickeyid = msgget(ipcMickey, IPC_CREAT | 0666); 

    ipcDonald = ftok("/tmp/mqdonald", 69); 
     mqDonaldid = msgget(ipcDonald, IPC_CREAT | 0666); 

    pthread_create(&t1, NULL, MICKEYthreadFunc, "Mickey sends\n"); 
    pthread_create(&t2, NULL, MINNIEthreadFunc, "Minnie replies\n"); 
    pthread_create(&t3, NULL, DONALDthreadFunc, "Donald sends\n"); 
    pthread_create(&t4, NULL, PLUTOthreadFunc, "Pluto replies\n"); 

    while(1) 
    { 
     sleep(5); 
    } 
} 
+0

+1 न्यूनतम उदाहरण के संकलन के लिए, – sehe

उत्तर

5

समस्या आप त्रुटि हैंडलिंग याद किया है।

शामिल

ipcMickey = ftok("/tmp/mqmickey", 63); 
if (-1==ipcMickey) 
{ 
    perror("ipcMickey"); 
    exit(255); 
} 
ipcDonald = ftok("/tmp/mqdonald", 69); 
if (-1==ipcDonald) 
{ 
    perror("ipcDonald"); 
    exit(255); 
} 

और आप जल्दी ही

./mm 
ipcDonald: No such file or directory 

ftok की वापसी है -1 उस मामले में मिल जाएगा। दोनों फ़ाइलों को याद कर रहे हैं, तो दोनों आईपीसी कुंजी -1 हो जाएगा, जिसका अर्थ है सभी यातायात के शेयरों में एक ही बंदरगाह :)

तो

touch /tmp/mqmickey /tmp/mqdonald 

फिक्स यह। कुछ आंकड़े (usleep(random()%10000) साथ सोता की जगह):

gcc MM.c -o mm -O3 -fno-stack-protector -pthread 
time ./mm | { trap "" INT; sort | uniq -c | tee stats; } 
    16047 
     1 Donald sent a 
    8054 Donald sent a message to Pluto. 
     1 Donald thread successfully started. 
    8040 Mickey sent a message to Minnie. 
     1 Mickey thread successfully started. 
    8065 Minnie received: Hello, Minnie! 
     1 Minnie thread successfully started. 
    7982 Pluto received: Sit, Pluto! 
     1 Pluto thread successfully started. 


real 0m40.814s 
user 0m0.168s 
sys 0m0.092s 
+2

परीक्षण यह भी असंभव है, लेकिन अब तक संभावना के दायरे के भीतर है कि 'ftok' दोनों फ़ाइल नामों के लिए एक ही कुंजी देता है। कभी-कभार टक्कर से बचने के लिए इसमें बस कुछ बिट्स होते हैं। ओपी को पॉज़िक्स संदेश कतार ('mq_ *') में देखने पर विचार करना चाहिए, जिसमें इस मौलिक दोष की कमी है। वैकल्पिक रूप से, आप अस्थायी फ़ाइलों को तब तक बना सकते हैं जब तक आप अनन्य कुंजी प्राप्त नहीं कर लेते हैं और फिर उन सभी थ्रेड/प्रक्रियाओं के साथ चाबियाँ साझा करते हैं जिन्हें उन्हें फिर से 'ftok'' कॉल करने की बजाय आवश्यकता होती है। –

0

यहाँ थोड़ा अपने कार्यक्रम के संस्करण संशोधित किया गया है:

/* 
    To compile; 
    gcc MM.c -o mm -fno-stack-protector -pthread 

    We want Mickey to send a message to Minnie exclusively. 
    We want Donald to send a message to pluto exclusively. 

    Problem: Pluto intercepts Minnie's messages. 

    Listing gives: 

    $ ./mm 
    Mickey thread successfully started. 
    Minnie thread successfully started. 
    Pluto thread successfully started. 
    Donald thread successfully started. 
    Donald sent a message to Pluto. 
    Mickey sent a message to Minnie. 
    Pluto received: Sit, Pluto! 

    Minnie received: Hello, Minnie! 

    Mickey sent a message to Minnie. (100 times) 

    Pluto received: Hello, Minnie! 
*/ 
#include <sys/types.h> 
#include <sys/msg.h> 
#include <sys/ipc.h> 
#include <string.h> 
#include <stdio.h> 

pthread_t t1,t2,t3,t4; 

// Mickey send 
key_t ipcMickey; 
int mqMickeyid; 
char helloMickeymsg[] = {"Hello, Minnie!"}; 
struct { long type; char text[100]; } myMickeymsg; 

// Minnie get 
int mqMinnieid; 
struct { long type; char text[100]; } myMinniemsg; 

// Donald send 
key_t ipcDonald; 
int mqDonaldid; 
char helloDonaldmsg[] = {"Sit, Pluto!"}; 
struct { long type; char text[100]; } myDonaldmsg; 

// Pluto get 
int mqPlutoid; 
struct { long type; char text[100]; } myPlutomsg; 

static void * DONALDthreadFunc(void *arg) 
{ 
    printf("Donald thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //send 
     memset(myDonaldmsg.text, 0, 100); 
     strncpy(myDonaldmsg.text, helloDonaldmsg, strlen(helloDonaldmsg)); 
     myDonaldmsg.type = 1; 
     msgsnd(mqDonaldid, &myDonaldmsg, sizeof(myDonaldmsg), 0); 
     printf("Donald sent a message to Pluto.\r\n"); 
     sleep(4); 
    } 

    /* just a formality */ 
    return (void *) strlen(s); 
} 

static void * PLUTOthreadFunc(void *arg) 
{ 
    printf("Pluto thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //receive 
     mqPlutoid = msgget(ipcDonald, 0); 
     msgrcv(mqPlutoid, &myPlutomsg, sizeof(myPlutomsg), 0, 0); 
     printf("Pluto received: %s\r\nPluto uses MQ with id = %d\r\n", myPlutomsg.text,mqPlutoid); 
     sleep(1); 
    } 

    /* just a formality */ 
    return (void *) strlen(s); 
} 

static void * MICKEYthreadFunc(void *arg) 
{ 
    printf("Mickey thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //send 
     memset(myMickeymsg.text, 0, 100); 
     strncpy(myMickeymsg.text, helloMickeymsg, strlen(helloMickeymsg)); 
     myMickeymsg.type = 1; 
     msgsnd(mqMickeyid, &myMickeymsg, sizeof(myMickeymsg), 0); 
     printf("Mickey sent a message to Minnie.\r\n"); 
     usleep(10000); 
    } 

    /* just a formality */ 
    return (void *) strlen(s); 
} 

static void * MINNIEthreadFunc(void *arg) 
{ 
    printf("Minnie thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //receive 
     mqMinnieid = msgget(ipcMickey, 0); 
     msgrcv(mqMinnieid, &myMinniemsg, sizeof(myMinniemsg), 0, 0); 
     printf(" Minnie received: %s\r\nMinnie uses MQ with id = %d\r\n", myMinniemsg.text,mqMinnieid); 
     sleep(3); 
    } 

    return (void *) strlen(s); 
} 

int main (void) 
{ 
    ipcMickey = ftok("./mqmickey", 63); 
    mqMickeyid = msgget(ipcMickey, IPC_CREAT | 0666); 
    printf("mqMickeyid=%d\n",mqMickeyid); 

    ipcDonald = ftok("./mqdonald", 69); 
    mqDonaldid = msgget(ipcDonald, IPC_CREAT | 0666); 
    printf("mqDonaldid=%d\n",mqDonaldid); 

    pthread_create(&t1, NULL, MICKEYthreadFunc, "Mickey sends\n"); 
    pthread_create(&t2, NULL, MINNIEthreadFunc, "Minnie replies\n"); 
    pthread_create(&t3, NULL, DONALDthreadFunc, "Donald sends\n"); 
    pthread_create(&t4, NULL, PLUTOthreadFunc, "Pluto replies\n"); 

    while(1) 
    { 
     sleep(5); 
    } 
} 

मुझे पता चला है कि किसी कारण से, msgget विफल रहता है, और दोनों MQS हो रही है एक ही आईडी, तो यह एक दौड़ है जो थ्रेड पहले में जाती है।

अपने कार्यक्रम के इस संशोधित संस्करण के साथ

, ऐसा करते हैं:

touch mqmickey 
touch mqdonald 

पहले फ़ाइलें बनाने के लिए।

और आपको संदेश प्राप्तकर्ताओं को सही करने के लिए संदेश देखना चाहिए।

2

आपको बहुत बहुत sehe और VJo धन्यवाद,

इधर, कार्यक्रम का एक संशोधित संस्करण है को ध्यान में आपकी सभी टिप्पणियां लेने।

आशा है कि यह किसी और के लिए उपयोगी होगा।

बर्ट

/* 
    We want Mickey to send a message to Minnie exclusively. 
    We want Donald to send a message to pluto exclusively. 

    To compile: 
    gcc mm.c -o mm -fno-stack-protector -pthread 

    Requires: 
    syslog enabled and started. 

    To test: 
    time ./mm | { trap "" INT; sort | uniq -c | tee stats; } 

    Results: 
    1503373 Donald sent a message to Pluto. 
      1 Donald thread successfully started. 
    1423964 Mickey sent a message to Minnie. 
      1 Mickey thread successfully started. 
    1423958 Minnie received: Hello, Minnie! 
      1 Minnie thread successfully started. 
    1503333 Pluto received: Sit, Pluto! 
      1 Pluto thread successfully started. 

    real 0m17.133s 
    user 0m16.053s 
    sys 0m5.248s 

*/ 
#include <sys/types.h> 
#include <sys/msg.h> 
#include <sys/ipc.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <syslog.h> 


#define MQMICKEY "/tmp/MQMickey" 
#define MQDONALD "/tmp/MQDonald" 

pthread_t t1,t2,t3,t4; 
FILE *fMickeypointer; 
FILE *fDonaldpointer; 

// Mickey send 
key_t ipcMickey; 
int mqMickeyid; 
char helloMickeymsg[] = {"Hello, Minnie!"}; 
struct { long type; char text[100]; } myMickeymsg; 

// Minnie get 
int mqMinnieid; 
struct { long type; char text[100]; } myMinniemsg; 

// Donald send 
key_t ipcDonald; 
int mqDonaldid; 
char helloDonaldmsg[] = {"Sit, Pluto!"}; 
struct { long type; char text[100]; } myDonaldmsg; 

// Pluto get 
int mqPlutoid; 
struct { long type; char text[100]; } myPlutomsg; 

static void * DONALDthreadFunc(void *arg) 
{ 
    printf("Donald thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //send 
     memset(myDonaldmsg.text, 0, 100); 
     strncpy(myDonaldmsg.text, helloDonaldmsg, strlen(helloDonaldmsg)); 
     myDonaldmsg.type = 1; 
     msgsnd(mqDonaldid, &myDonaldmsg, sizeof(myDonaldmsg), 0); 
     printf("Donald sent a message to Pluto.\r\n"); 
    } 

    /* just a formality */ 
    return (void *) strlen(s); 
} 

static void * PLUTOthreadFunc(void *arg) 
{ 
    printf("Pluto thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //receive 
     mqPlutoid = msgget(ipcDonald, 0); 
     msgrcv(mqPlutoid, &myPlutomsg, sizeof(myPlutomsg), 0, 0); 
     printf("Pluto received: %s\r\n", myPlutomsg.text); 
    } 

    /* just a formality */ 
    return (void *) strlen(s); 
} 

static void * MICKEYthreadFunc(void *arg) 
{ 
    printf("Mickey thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //send 
     memset(myMickeymsg.text, 0, 100); 
     strncpy(myMickeymsg.text, helloMickeymsg, strlen(helloMickeymsg)); 
     myMickeymsg.type = 1; 
     msgsnd(mqMickeyid, &myMickeymsg, sizeof(myMickeymsg), 0); 
     printf("Mickey sent a message to Minnie.\r\n"); 
    } 

    /* just a formality */ 
    return (void *) strlen(s); 
} 

static void * MINNIEthreadFunc(void *arg) 
{ 
    printf("Minnie thread successfully started.\n"); 
    char *s = (char *) arg; 

    while(1) 
    { 
     //receive 
     mqMinnieid = msgget(ipcMickey, 0); 
     msgrcv(mqMinnieid, &myMinniemsg, sizeof(myMinniemsg), 0, 0); 
     printf(" Minnie received: %s\r\n", myMinniemsg.text); 
    } 

    return (void *) strlen(s); 
} 

int main (void) 
{ 
    /* 
     MUST create the target files first. 

     The return of ftok is -1 if file is missing. If BOTH files are missing, both ipc keys 
     will be -1, meaning all traffic shares the same port. Result: one queue will acquire 
     messages not intended for it! 
    */ 
    fMickeypointer = fopen(MQMICKEY, "a"); 
    if(fMickeypointer == NULL) 
    { 
     printf("Failed to create Mickey queue file.\n"); 

     /* system logging */ 
     setlogmask (LOG_UPTO (LOG_NOTICE)); 
     openlog ("MickeyDonald", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); 
     syslog (LOG_NOTICE, "Failed to create Mickey queue file."); 
     closelog(); 
     exit(91); 
    } 

    fDonaldpointer = fopen(MQDONALD, "a"); 
    if(fDonaldpointer == NULL) 
    { 
     printf("Failed to create Donald queue file.\r\n"); 

     /* system logging */ 
     setlogmask (LOG_UPTO (LOG_NOTICE)); 
     openlog ("MickeyDonald", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); 
     syslog (LOG_NOTICE, "Failed to create Donald queue file."); 
     closelog(); 
     exit(92); 
    } 

    ipcMickey = 0; 
    ipcDonald = 0; 

    /* make sure we assign DIFFERENT ipc values */ 
    while(ipcMickey == ipcDonald) 
    { 
     ipcMickey = ftok(MQMICKEY, 63); 
     if (-1==ipcMickey) 
     { 
      printf("ipcMickey does not exist.\r\n"); 

      /* system logging */ 
      setlogmask (LOG_UPTO (LOG_NOTICE)); 
      openlog ("MickeyDonald", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); 
      syslog (LOG_NOTICE, "Failed to ftok Mickey file."); 
      closelog(); 
      exit(93); 
     } 

     ipcDonald = ftok(MQDONALD, 69); 
     if (-1==ipcDonald) 
     { 
      printf("ipcDonald does not exist.\r\n"); 

      /* system logging */ 
      setlogmask (LOG_UPTO (LOG_NOTICE)); 
      openlog ("MickeyDonald", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); 
      syslog (LOG_NOTICE, "Failed to ftok Donald file."); 
      closelog(); 
      exit(94); 
     } 
    } 

    mqMickeyid = msgget(ipcMickey, IPC_CREAT | 0666); 
    mqDonaldid = msgget(ipcDonald, IPC_CREAT | 0666); 

    pthread_create(&t1, NULL, MICKEYthreadFunc, "Mickey sends\n"); 
    pthread_create(&t2, NULL, MINNIEthreadFunc, "Minnie replies\n"); 
    pthread_create(&t3, NULL, DONALDthreadFunc, "Donald sends\n"); 
    pthread_create(&t4, NULL, PLUTOthreadFunc, "Pluto replies\n"); 

    long exitcounter = 0; 
    while(exitcounter < 100000) 
    { 
     exitcounter +=1;   
     usleep(100); 
    } 
    exit(0); 
} 
+0

चीयर्स, खुशी हुई यह मदद की :) – sehe

संबंधित मुद्दे