Screwface
03-09-2008, 09:41
Ciao a tutti. Sto cercando di combinare qualcosa con la comunicazione fra processi ma sono alle prime armi, ed ho incontrato un problema: ho scritto il seguente codice, che nelle mie intenzioni dovrebbe mostrare un menù, dal quale è possibile indirizzare un messaggio ad uno fra tre processi, eliminare i messaggi memorizzati o visualizzarli.
A seconda del tipo di azione scelta costruisco un messaggio, dove memorizzo il destinatario, il tipo di messaggio (1 se inserisco un msg, 2 se lo elimino ecc.), e lo invio tramite una coda a un altro processo. Qui, a seconda del numero di destinatario, lo invio ad un'altra coda, differente a seconda del destinatario, e un nuovo processo dovrebbe poi svolgere le azioni del caso (ricezione messaggio, eliminazione, visualizzazione ecc, per ora ho scritto solamente la ricezione del messaggio). Il problema è che quando avvio il programma una prima volta sembra funzionare perfettamente, ma quando lo riavvio successivamente ottengo un errore "Segmentation fault". Qualche suggerimento?
Riporto ciò che ho scritto:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/types.h>
#define MSGSZ 128
main ()
{
int msqid, msqid1, msqid2, msqid3;
int status;
int msgflg = IPC_CREAT | 0666;
key_t key;
key_t key1, key2, key3, keyK;
size_t buf_length;
int pid_interfaccia;
int pid_upost, pid1, pid2, pid3;
int temp, temp1, temp2, temp3, temp4;
int risposta;
int i;
int c;
int maxmsgsz;
int msgsz;
struct msgbuf {
long mtype;
char mtext[MSGSZ];
long destinatario;
} *sbuf, *rbuf, *rbuf1, *rbuf2, *rbuf3;
do
{
printf("\n\t\t1) Inviare un nuovo messaggio");
printf("\n\t\t2) Visualizzare i messaggi memorizzati");
printf("\n\t\t3) Eliminare i messaggi memorizzati");
printf("\n\t\t4) Uscire dal programma");
printf("\n\n\t\tScegliere un'opzione e premere INVIO\n");
sbuf = (struct msgbuf*)malloc((unsigned)(sizeof(struct msgbuf) - sizeof sbuf->mtext + 128));
do {
(void) scanf("%d", &risposta);
} while ((risposta < 1) || (risposta > 4));
switch(risposta) {
case 1:
{
printf("\nInserire il numero del destinatario: ");
scanf("%d",&sbuf->destinatario);
sbuf->mtype = 1;
printf("\nInserire il messaggio (max 128 caratteri): ");
while ((c = getchar()) != '\n' && c != EOF);
for (i = 0; ((c = getchar()) != '\n'); i++){
sbuf->mtext[i] = c;
}
key = ftok("/home/.../file.tmp", 'a'); /*file generato prima per la ftok*/
if (msqid = msgget(key, msgflg) < 0)
{
perror("\nErrore nella msgget\n");
exit(1);
}
else
{
buf_length = MSGSZ;
printf("\nmsgget eseguita con successo: %d\n", msqid);
if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0)
{
printf("\n%d, &d, %s\n", msqid, sbuf->mtype, sbuf->mtext);
perror("\nErrore nella msgsnd\n");
exit(1);
}
}
break;
}
case 2:
{
printf("\nInserire il numero dell'archivio: ");
scanf("%d", &sbuf->destinatario);
sbuf->mtype = 2;
(void) strcpy(sbuf->mtext, "Richiesta visualizzazione archivio X");
if ((msqid = msgget(key, msgflg)) < 0)
{
perror("\nErrore nella msgget\n");
exit(1);
}
else
{
buf_length = MSGSZ;
printf("\nmsgget eseguita con successo: %d\n", msqid);
if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0)
{
perror("\nErrore nella msgsnd\n");
exit(1);
}
}
break;
}
case 3:
{
printf("\nInserire il numero dell'archivio da cancellare: ");
scanf("%d", &sbuf->destinatario);
sbuf->mtype = 3;
(void) strcpy(sbuf->mtext, "Richiesta eliminazione archivio X");
if ((msqid = msgget(key, msgflg)) < 0)
{
perror("Errore nella msgget");
exit(1);
}
else
{
buf_length = MSGSZ;
printf("\nmsgget eseguita con successo: %d\n", msqid);
if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0)
{
printf("\n&d, &d, &s\n", msqid, sbuf->mtype, sbuf->mtext);
perror("Errore nella msgsend\n");
exit(1);
}
}
break;
}
case 4:
{
exit(0);
}
}
pid_upost = fork();
if (pid_upost == 0)
{
rbuf = (struct msgbuf*)malloc((unsigned)(sizeof(struct msgbuf) - sizeof sbuf->mtext + 128));
if (rbuf == NULL) {
printf("\n\nErrore: impossibile allocare il messaggio");
exit(1);
}
temp = msgrcv(msqid, &rbuf, MSGSZ, 0, MSG_NOERROR);
if (temp < 0)
{
perror("\nErrore nella msgrcv\n");
exit(1);
}
switch (rbuf->destinatario) {
case 1:
{
keyK = ftok("/home/...../file1.tmp", 'b');
if (msqid1 = msgget(keyK, IPC_CREAT | 0666) < 0)
{
perror("\nErrore nella seconda msgget\n");
exit(1);
}
buf_length = MSGSZ;
if (msgsnd(msqid1, &rbuf, buf_length, IPC_NOWAIT) < 0)
{
printf("\n%d, &d, %s\n", msqid1, rbuf->mtype, rbuf->mtext);
perror("\nErrore nella seconda msgsnd\n");
exit(1);
}
pid1 = fork();
if (pid1 == 0)
{
rbuf1 = (struct msgbuf*)malloc((unsigned)(sizeof(struct msgbuf) - sizeof sbuf->mtext + 128));
if (rbuf1 == NULL) {
printf("\n\nErrore: impossibile allocare il messaggio");
exit(1);
}
temp1 = msgrcv(msqid1, &rbuf1, MSGSZ, 0, MSG_NOERROR);
if (temp1 < 0)
{
perror("\nErrore nella seconda msgrcv\n");
exit(1);
}
else
{
printf("\nMESSAGGIO RICEVUTO!\n");
}
break; /
}
}
}
exit(0);
}
}
while (risposta != 4);
}
Qualcuno sa darmi un aiuto? Di solito l'errore (Segmentation fault) si verifica dopo aver eseguito con successo la prima msgget, e solamente quando eseguo il programma le volte successive alla prima (a volte anche seconda). Grazie a tutti.
A seconda del tipo di azione scelta costruisco un messaggio, dove memorizzo il destinatario, il tipo di messaggio (1 se inserisco un msg, 2 se lo elimino ecc.), e lo invio tramite una coda a un altro processo. Qui, a seconda del numero di destinatario, lo invio ad un'altra coda, differente a seconda del destinatario, e un nuovo processo dovrebbe poi svolgere le azioni del caso (ricezione messaggio, eliminazione, visualizzazione ecc, per ora ho scritto solamente la ricezione del messaggio). Il problema è che quando avvio il programma una prima volta sembra funzionare perfettamente, ma quando lo riavvio successivamente ottengo un errore "Segmentation fault". Qualche suggerimento?
Riporto ciò che ho scritto:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/types.h>
#define MSGSZ 128
main ()
{
int msqid, msqid1, msqid2, msqid3;
int status;
int msgflg = IPC_CREAT | 0666;
key_t key;
key_t key1, key2, key3, keyK;
size_t buf_length;
int pid_interfaccia;
int pid_upost, pid1, pid2, pid3;
int temp, temp1, temp2, temp3, temp4;
int risposta;
int i;
int c;
int maxmsgsz;
int msgsz;
struct msgbuf {
long mtype;
char mtext[MSGSZ];
long destinatario;
} *sbuf, *rbuf, *rbuf1, *rbuf2, *rbuf3;
do
{
printf("\n\t\t1) Inviare un nuovo messaggio");
printf("\n\t\t2) Visualizzare i messaggi memorizzati");
printf("\n\t\t3) Eliminare i messaggi memorizzati");
printf("\n\t\t4) Uscire dal programma");
printf("\n\n\t\tScegliere un'opzione e premere INVIO\n");
sbuf = (struct msgbuf*)malloc((unsigned)(sizeof(struct msgbuf) - sizeof sbuf->mtext + 128));
do {
(void) scanf("%d", &risposta);
} while ((risposta < 1) || (risposta > 4));
switch(risposta) {
case 1:
{
printf("\nInserire il numero del destinatario: ");
scanf("%d",&sbuf->destinatario);
sbuf->mtype = 1;
printf("\nInserire il messaggio (max 128 caratteri): ");
while ((c = getchar()) != '\n' && c != EOF);
for (i = 0; ((c = getchar()) != '\n'); i++){
sbuf->mtext[i] = c;
}
key = ftok("/home/.../file.tmp", 'a'); /*file generato prima per la ftok*/
if (msqid = msgget(key, msgflg) < 0)
{
perror("\nErrore nella msgget\n");
exit(1);
}
else
{
buf_length = MSGSZ;
printf("\nmsgget eseguita con successo: %d\n", msqid);
if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0)
{
printf("\n%d, &d, %s\n", msqid, sbuf->mtype, sbuf->mtext);
perror("\nErrore nella msgsnd\n");
exit(1);
}
}
break;
}
case 2:
{
printf("\nInserire il numero dell'archivio: ");
scanf("%d", &sbuf->destinatario);
sbuf->mtype = 2;
(void) strcpy(sbuf->mtext, "Richiesta visualizzazione archivio X");
if ((msqid = msgget(key, msgflg)) < 0)
{
perror("\nErrore nella msgget\n");
exit(1);
}
else
{
buf_length = MSGSZ;
printf("\nmsgget eseguita con successo: %d\n", msqid);
if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0)
{
perror("\nErrore nella msgsnd\n");
exit(1);
}
}
break;
}
case 3:
{
printf("\nInserire il numero dell'archivio da cancellare: ");
scanf("%d", &sbuf->destinatario);
sbuf->mtype = 3;
(void) strcpy(sbuf->mtext, "Richiesta eliminazione archivio X");
if ((msqid = msgget(key, msgflg)) < 0)
{
perror("Errore nella msgget");
exit(1);
}
else
{
buf_length = MSGSZ;
printf("\nmsgget eseguita con successo: %d\n", msqid);
if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0)
{
printf("\n&d, &d, &s\n", msqid, sbuf->mtype, sbuf->mtext);
perror("Errore nella msgsend\n");
exit(1);
}
}
break;
}
case 4:
{
exit(0);
}
}
pid_upost = fork();
if (pid_upost == 0)
{
rbuf = (struct msgbuf*)malloc((unsigned)(sizeof(struct msgbuf) - sizeof sbuf->mtext + 128));
if (rbuf == NULL) {
printf("\n\nErrore: impossibile allocare il messaggio");
exit(1);
}
temp = msgrcv(msqid, &rbuf, MSGSZ, 0, MSG_NOERROR);
if (temp < 0)
{
perror("\nErrore nella msgrcv\n");
exit(1);
}
switch (rbuf->destinatario) {
case 1:
{
keyK = ftok("/home/...../file1.tmp", 'b');
if (msqid1 = msgget(keyK, IPC_CREAT | 0666) < 0)
{
perror("\nErrore nella seconda msgget\n");
exit(1);
}
buf_length = MSGSZ;
if (msgsnd(msqid1, &rbuf, buf_length, IPC_NOWAIT) < 0)
{
printf("\n%d, &d, %s\n", msqid1, rbuf->mtype, rbuf->mtext);
perror("\nErrore nella seconda msgsnd\n");
exit(1);
}
pid1 = fork();
if (pid1 == 0)
{
rbuf1 = (struct msgbuf*)malloc((unsigned)(sizeof(struct msgbuf) - sizeof sbuf->mtext + 128));
if (rbuf1 == NULL) {
printf("\n\nErrore: impossibile allocare il messaggio");
exit(1);
}
temp1 = msgrcv(msqid1, &rbuf1, MSGSZ, 0, MSG_NOERROR);
if (temp1 < 0)
{
perror("\nErrore nella seconda msgrcv\n");
exit(1);
}
else
{
printf("\nMESSAGGIO RICEVUTO!\n");
}
break; /
}
}
}
exit(0);
}
}
while (risposta != 4);
}
Qualcuno sa darmi un aiuto? Di solito l'errore (Segmentation fault) si verifica dopo aver eseguito con successo la prima msgget, e solamente quando eseguo il programma le volte successive alla prima (a volte anche seconda). Grazie a tutti.