[C]errore shared memory unix

di Anonimizzato9647 il
8 risposte
Ho iniziato da poco con la programmazione c in unix e ho diversi problemi...
ad esempio mi sapete dire perchè non funziona questo codice? cioè in compilazione va tutto bene ma in compilazione mi da errore cioè non da il risultato richiesto...
praticamente ho due file .c e uno dei in una zona di memoria condivisa mette 2 interi, l'altro li somma e poi ritorna il controllo al primo che stampa il risutlato a video.
qui sotto il codice
ADDER:

#include <sys/types.h>
#include <sys/sem.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#define SEMPERM 0600

typedef union _semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
}semun;
int initsem (key_t semkey){
    int status=0, semid;
    semid=semget(semkey, 1 , SEMPERM | IPC_CREAT | IPC_EXCL);
    if (semid==-1){
        if (errno=EEXIST){semid=semget(semkey,1,0);}
    } else {
        semun arg;
        arg.val=0;
        status=semctl(semid,0,SETVAL,arg);
    }
    if (semid==-1 | status==-1){
        perror("initsem fallita");
        return (-1);
    }
    return (semid);
}
int waitSem(int semid){
    struct sembuf wait_buf;
    wait_buf.sem_num=0;
    wait_buf.sem_op=1;
    wait_buf.sem_flg=SEM_UNDO;
    if (semop(semid,&wait_buf, 1)==-1){
        perror("waitSem Fallita");
        exit(-1);
    }
    return 0;
}

int signalSem (int semid){
    struct sembuf signal_buf;
    signal_buf.sem_num=0;
    signal_buf.sem_op=1;
    signal_buf.sem_flg=SEM_UNDO;
    if (semop(semid,&signal_buf,1)==-1){
        perror("signalSem fallita");
        exit(1);
    }
    return 0;
}
int main(){
    int id,*point,a,b,c;
    key_t keysem=0x050,chiavemem=0x100;
    int sem,buffer[2];
    sem=initsem(keysem);
    if (sem<0){
        perror("errore creazione semaforo");
        exit(-1);
    }
    id=shmget(chiavemem,sizeof(buffer),0666|IPC_CREAT);
    point=(int *)shmat(id,NULL,0); 
    point[0]=a;
    point[1]=b;
    waitSem(sem);
    c=a+b;
    point[2]=c;
    signalSem(sem);
    shmdt(point);
    exit(0);
}
MAIN

#include <sys/types.h>
#include <sys/sem.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <stdlib.h>
#define SEMPERM 0600

typedef union _semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
}semun;
int initsem (key_t semkey){
    int status=0, semid;
    semid=semget(semkey, 1 , SEMPERM | IPC_CREAT | IPC_EXCL);
    if (semid==-1){
        if (errno=EEXIST){semid=semget(semkey,1,0);}
    } else {
        semun arg;
        arg.val=0;
        status=semctl(semid,0,SETVAL,arg);
    }
    if (semid==-1 | status==-1){
        perror("initsem fallita");
        return (-1);
    }
    return (semid);
}
int waitSem(int semid){
    struct sembuf wait_buf;
    wait_buf.sem_num=0;
    wait_buf.sem_op=1;
    wait_buf.sem_flg=SEM_UNDO;
    if (semop(semid,&wait_buf, 1)==-1){
        perror("waitSem Fallita");
        exit(-1);
    }
    return 0;
}

int signalSem (int semid){
    struct sembuf signal_buf;
    signal_buf.sem_num=0;
    signal_buf.sem_op=1;
    signal_buf.sem_flg=SEM_UNDO;
    if (semop(semid,&signal_buf,1)==-1){
        perror("signalSem fallita");
        exit(1);
    }
    return 0;
}
int main (){
    key_t chiavemem=0x100,keysem=0x050;
    int sem,a,id,*point;
    pid_t figlio;
    int buffer[2];
    sem=initsem(keysem);
    if(sem<0){
        perror ("creazione semaforo fallita");
        exit (-1);
    }
    id=shmget(chiavemem,sizeof(buffer),0666|IPC_CREAT);
    point=(int *)shmat(id,NULL,0);
    waitSem(sem);
    point[0]=3;
    point[1]=5;
    signalSem(sem);
    figlio=fork();
    if (figlio<0){
        perror("fork fallita");
        exit (-1);
    }
    if (figlio==0){
        execvp("/home/francesco/NetBeansProjects/Esercizio1/addizione",NULL);
        a=point[2];
        exit(0);
    }
    shmdt(point);
    shmctl(id,IPC_RMID,0);
    printf("il risultato è %d",a);
    exit(0);
}

8 Risposte

  • Sia su ADDER che su MAIN correggi:
     
          ...
          // doppio uguale per confronto, singolo uguale per assegnamento
    #20   if (errno==EEXIST){semid=semget(semkey,1,0);} 
          ...
          // || OR
    #26   if (semid==-1 || status==-1)
          ...
          // le variabili a b non sono inizializzate
    #66   point[0]=a;  
    #67   point[1]=b;
          ...
    
  • Non funziona ugualmente mi da come risultato numeri assurdi tipo 1447484 come risultato tra 3 e 5
  • Francesco, nel main, la printf di a da dove viene?
  • Non capisco...viene dal main, cioè l'ho dichiarata nel main...volendo se ne potrebbe fare a meno perchè sarebbe l'ultimo elemento del buffer che l'adder riempie.
    detta in poche parole il main mette sui primi due elementi del buffer due numeri, richiama l'adder che legge i due numeri dal buffer poi li somma e mette il risultato nell'ultimo elemento del buffer poi il main legge il contenuto di quest'ultimo e lo stampa a video.
    il fatto è che così mi stampa a video non la somma di 3 e 5 ma numeri tipo 11248567 o cose del genere...
  • Francesco, nel main, la printf di a da dove viene?
    ADDR:
    
        ....
        int buffer[2]  // <--- Qui
        ....
        point=(int *)shmat(id,NULL,0); 
        point[0]=a; //???? forse il contrario
        point[1]=b; //???? idem
        waitSem(sem);
        c=a+b;
        point[2]=c; //???? non esiste il 2
        signalSem(sem);
        ....
    
  • Il 2 non esiste ma infatti deve metterci il valore di c
    praticamente sarebbe
    
    point[2]=point[0]+point[1];
    
    si lo so il buffer è di 2 ma mi hanno detto di mettere 3...vabbè al massimo lascio una posizione vuota nell'array
  • Nessuno?
  • Francesco, a me funziona con le modifiche apportate.
    Un'accorgimento che non ti ho detto è che main deve attendere che adder abbia scritto il resultato, altrimenti rischi che il 'parent' venga eseguito prima della scrittura del 'child'.
    Questo lo puoi fare sia dalla gestione semaforica oppure semplicemente usando un byte sharato per indicarti lo status (READY/BUSY...).
Devi accedere o registrarti per scrivere nel forum
8 risposte