/* Esimerkki viestin välityksestä viestijonon kautta: lähetys ja vastaanotto * * Esimerkki siitä, miten deadlock-tilanne eli lukkiutuminen * esimerkiksi voi tapahtua ohjelmointivirheen takia *joissain * tilanteissa* ja taas joissain tilanteissa homma toimii kuten on * suunniteltu. Tämä lelu-chatti periaatteessa toimii kahden * keskustelijan välillä oikein hyvin, **paitsi** jos jompikumpi * jossain vaiheessa sattuu sanomaan esimerkiksi, että "Eipä tässä sen * kummempaa kuulu..." tai muuta isolla E-kirjaimella alkavaa... * * ÄLÄ KOKEILE esimerkkiä käytännössä yhteiskäytössä olevilla koneilla * ellet ole äärimmäisen vahvasti hajulla siitä, mitä tapahtuu! * * Jos kokeilet, niin mieluiten koti-Linuxilla tai joka tapauksessa * jossain, missä ihan itse olet järjestelmänvalvoja. Liikutaan * alueella, jossa on helppo aiheuttaa itkua ja hammastenkiristelyä * kaikille kyseisen tietokoneen käyttäjille... * * Tämä nähdään luennolla ja tätä voi lukea näytöltä ja koettaa * hahmottaa toimintaa jollain tasolla. Käytännössä tultaneen jotain * tällaisia kokeilemaan vapaaehtoisissa demoissa 3 ja 4 * erikoismikroluokassa, jonka koneita saa buutata mielin määrin, jos * ne menevät sekaisin. Luokka on auki toimistoaikaan, ja siellä ei * ole kesällä muuta toimintaa, joten sinne voi mennä milloin vain * kokeilemaan ne, kellä ei ole kotona Linuxia. Luokan käyttö * opastetaan demo 3:n materiaalissa ja tilaisuuksissa. * * JOS olet turvallisessa paikassa ja haluat kokeilla, niin käynnistä * prosessit näillä argumenteilla: * * chattomyself 1 2 # Tällä on ensimmäinen puheenvuoro * * chattomyself 2 1 # Tällä on toinen ja niin edelleen puheenvuoro * * Stolen and adapted, with utmost gratitude, from: * http://www.cs.cf.ac.uk/Dave/C/node25.html#SECTION002500000000000000000 */ #include #include #include #include #include #include #define MSGSZ 128 /* C:ssä ei ole kunnon syöttöaliohjelmia. Rykäistään oma (eli * pollitään netistä jonkun tekele, joka näyttää järkevältä...) */ int getline(char line[], int max) { int nch = 0; int c; max = max - 1; /* leave room for '\0' */ while((c = getchar()) != EOF) { if(c == '\n') break; if(nch < max) { line[nch] = c; nch = nch + 1; } } if(c == EOF && nch == 0) return EOF; line[nch] = '\0'; return nch; } /* * Määritellään, millaisia viestejä oma sovellus lähettelee. * Kokonaisluku pitää olla kaikissa viesteissä (se on määritelty * käyttöjärjestelmäkutsujen rajapinnassa). Tässä meidän viestiosa on * merkkijono, mutta se voisi olla mikä tahansa muukin tietorakenne, * kunhan sen pituus tavuina tiedetään. */ typedef struct msgbuf { long mtype; char mtext[MSGSZ]; } message_buf; /* Pääohjelma */ int main(int argc, char **argv) { int msqid; key_t key; message_buf buf; size_t buf_length; int i=0; long mytype, othertype; if (argc != 3){ fprintf (stderr, "Usage: %s mytype othertype\n", argv[0]); return 1; } mytype = atoi(argv[1]); othertype = atoi(argv[2]); /* Luodaan viestijono */ key = 1234; if ((msqid = msgget(key, IPC_CREAT | 0666 )) < 0) { perror("msgget"); exit(1); } /* Onnistui, jos ei virhettä...*/ fprintf(stderr,"Viestijonomme id = %d\n", msqid); while(1){ if (mytype == 1 || i >= 1){ printf("Kirjoita viesti: "); getline(&buf.mtext, MSGSZ); if (buf.mtext[0] != 'E') { /* Viestin lähetys, lähetetään 'othertype' tyyppinen */ buf.mtype = othertype; buf_length = strlen(buf.mtext) + 1 ; if (msgsnd(msqid, &buf, buf_length, IPC_NOWAIT) < 0) { perror("msgsnd"); exit(1); }else{ printf("Lähetetty: \"%s\"\n", buf.mtext); } if (strcmp(buf.mtext,"bye") == 0) break; } } printf("Odotan vastausta ...\n"); /* Vastaanotto, kuunnellaan 'mytype'-tyyppisiä */ if (msgrcv(msqid, &buf, MSGSZ, mytype, 0) < 0) { perror("msgrcv"); exit(1); } printf("Vastaanotettu: %s\n", buf.mtext); i++; } if (msgctl(msqid, IPC_RMID, 0) == -1) { perror("msgctl"); } exit(0); }