2016-11-24 4 views
1

У меня есть проблема с общим memrory в С.Проблемы с общей памятью в C

Я думаю, что я выделяю эти общие переменные памяти, но я не могу его удалить, и поэтому я не могу запустить мою программку без перезагрузки моего компьютер, потому что у меня проблема: эта разделяемая память уже существует.

Более того, я не уверен в использовании семафора.

Я должен использовать общую переменную, чтобы 2 processus должен увеличивать ее.

void prendre(int semid, int no){ 
    struct sembuf op[1]; 
    int er; 
    op[0].sem_num=no; 
    op[0].sem_op=-1; 
    op[0].sem_flg=0; 
    er=semop(semid,op,1); 
    if(er==-1) { perror("erreur semop prendre \n"); exit(1);} 
} 

void rendre(int semid, int no){ 
    struct sembuf op[1]; 
    int er; 
    op[0].sem_num=no; 
    op[0].sem_op=1; 
    op[0].sem_flg=0; 
    er=semop(semid,op,1); 
    if(er==-1) { perror("erreur semop prendre \n"); exit(1);} 
} 

void init_semaphore(int semid){ 
    int er; 
    union semun{ 
     int val; 
     struct semid_ds *buf; 
     ushort *array; 
    }arg; 
    arg.val=1; 
    er = semctl(semid,0,SETVAL,arg); 
    if(er == -1) {perror("erreur semctl\n");exit(1);} 
} 

void *runDuprocessus(int *pid, int *mem){ 
    int k=0; 
    for (k=0;k<1e6;k++){ 
     *mem += 1; 
    } 
    printf("globale processus %d = %d\n",*pid, *mem); 
    exit(1); 
} 

int creationSegment(int size, char *name, int cle){ 
    int shmid ; // l'identificateur de la memoire partagee 
    key_t clef ; // la clef associee au segment 

    clef = ftok(name,(key_t) cle) ; 
    shmid = shmget(clef, size, IPC_CREAT|IPC_EXCL|SHM_R|SHM_W) ; 
    if (shmid== -1) { 
     perror("Echec creation segment mémoire partagée!\n") ; 
     exit(1) ; 
    } 
    return shmid ; 
} 

int main(void){ 
    int destru; 
    pid_t pid; 
    int semid=0; 
    int *mem; 
    int shmid; // identifiant du segment de la mémoire partagé 
    int flag = 0; // flag du segment 
    char *name = (char*) malloc(25*sizeof(char)); 
    int size = sizeof(int); 
    key_t cle; 
    int tmp=0; 

// Création du segment de mémoire partagé 
name = "creationSegmentParatage.c"; 
shmid = creationSegment(size,name,2); 

// Création du sémaphore 
cle = ftok("proccessus.c",0); 
if(cle==(key_t) -1) {perror("erreur ftok\n");exit(1);} 

semid=semget(cle,1,IPC_CREAT|0666); 
if(semid == -1) {perror("erreur semget\n");exit(1);} 

init_semaphore(semid); //Initialisation du semaphore 
// Création du fork 
pid = fork(); 
if(pid < 0){ 
    printf("Erreur fork creation !\n"); 
    exit(0); 
}else if(pid == 0){ 
    //printf("Processus fils : \n"); 
    mem =shmat(shmid,0,flag);//Attachement segment mémoire 
    if(mem == (int*)-1){ 
     perror("Probleme attachement segment mémoire\n"); 
     exit(1); 
    } 
    prendre(semid,0); //Prise semaphore 
    runDuprocessus(&pid,mem); 
    tmp = shmdt(mem); 
    if(tmp ==-1){ //Détachement du segment mémoire 
     perror("detachement impossible\n") ; 
     exit(1) ; 
    } 
    rendre(semid,0); //Libération semaphore 
} 
else { 
    //printf("Processus père : \n"); 
    mem = shmat(shmid,0,flag); //Rattachement segment mémoire 
    if(mem == (int*)-1){ 
     perror("Probleme attachement segment mémoire\n"); 
     exit(1); 
    } 
    prendre(semid,0); 
    runDuprocessus(&pid,mem); 
    tmp = shmdt(mem); 
    if(tmp ==-1){ //Détachement du segment mémoire 
     perror("detachement impossible\n") ; 
     exit(1) ; 
    } 
    rendre(semid,0); 
} 
wait(NULL); //Attente du fils 
//Destruction du segment mémoire 
destru = shmctl(shmid,IPC_RMID,NULL); 
if (destru == -1){ 
    perror("Erreur lors de la destruction") ; 
    exit(1) ; 
} 
//Destruction du semaphore 
//sem_destroy(semid); 
return 0; 
} 

Благодарим за помощь в будущем!

+1

Обратите внимание, что вы можете использовать команду 'ipcs' для перечисления открытых объектов ssV IPC и команды' ipcrm' для удаления разделяемой памяти и других объектов IPC без перезагрузки компьютера. –

ответ

1

Я думаю, что я выделяю эту переменную разделяемой памяти, но я не могу ее удалить, поэтому я не могу запустить свою программу, не перезагружая компьютер, потому что у меня проблема: эта разделяемая память уже существует.

Вы получаете сегмент разделяемой памяти, как так ...

shmid = shmget(clef, size, IPC_CREAT|IPC_EXCL|SHM_R|SHM_W) ; 

Комбинация флаг IPC_CREAT|IPC_EXCL настаивает, что сегмент разделяемой памяти будет свеже создан. Если сегмент уже существует для указанного ключа, тогда вызов завершится с ошибкой, и это то, что вы, кажется, наблюдаете. Общие сегменты памяти сохраняются до тех пор, пока они не будут явно удалены, и есть много способов, которыми ваша программа может выйти без удаления сегмента.

Есть два основных варианта:

  1. Если это приемлемо для программы использовать сегмент разделяемой памяти, созданный во время предыдущего запуска - или другого одновременных один - то вы можете удалить IPC_EXCL флаг из shmget() звонок.

  2. Если вам действительно нужно, чтобы вы создавали новый, свежий сегмент для каждого прогона, вы должны убедиться, что сегмент удален, когда он больше не нужен. В частности, если потребность в сегменте заканчивается после выхода программы, вы должны убедиться, что после создания сегмента программа не выйдет - по крайней мере, не нормально - без повторного удаления сегмента.

Заметим также, что если при каждом запуске программы требуется собственный сегмент разделяемой памяти, то вы должны либо использовать различные ключи для различных серий, или признать, что только один экземпляр программы может работать в то время, , и если он выходит из строя, вы, возможно, придется вручную очистить - например, с ipcrm.

Если у вас есть вопросов об использовании семафора, тогда лучше было бы задать вопрос как отдельный вопрос.