C Ошибка сегментации устройства чтения-записи с общей памятью - PullRequest
1 голос
/ 20 мая 2019

Вот синхронизированный читатель и писатель. Цель - передача данных между этими двумя процессами через общую память. Модуль записи открывает общую память через структуру и записывает некоторые данные. Я получаю сообщение об ошибке Segmentation Fault (Core Dumped). Код компилируется с помощью следующей команды в Ubuntu.

g++ Writer.c -o Writer -lrt
g++ Reader.c -o Reader -lrt

И эти два Процесса управляются -

./Writer
./Reader    

The Writer.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(void){
    struct MemData{
        char* FileName;
        int LastByteLength;
        int ReadPointer;
        int WritePointer;
        char Data[512000];//MEMORY BLOCK SIZE: 500 KB
    };
    int SD;
    struct MemData *M;
    int NumberOfBuffers=10;
    int BufferSize=51200;//FILE BUFFER SIZE 50 KB

    SD= shm_open("/program.shared", O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
    if(SD< 0){
        printf("\nshm_open() error \n"); 
        return EXIT_FAILURE; 
    }
    fchmod(SD, S_IRWXU|S_IRWXG|S_IRWXO); 
    if(ftruncate(SD, sizeof(MemData))< 0){
        printf ("ftruncate() error \n");
        return EXIT_FAILURE; 
    }
    //THE FOLLOWING TYPECASTING AVOIDS THE NEED TO ATTACH THROUGH shmat() in shm.h HEADER I GUESS.
    M=(struct MemData*)mmap(NULL, sizeof(MemData), PROT_READ|PROT_WRITE, MAP_SHARED, SD, 0);
    if(M== MAP_FAILED){
        printf("mmap() error");
        return EXIT_FAILURE;
    }else{
        M->FileName=(char*)"xaa";
        M->LastByteLength=0;
        M->ReadPointer=-1;
        M->WritePointer=-1;
        memset(M->Data, '\0', strlen(M->Data));
    }
    /*
    FILE *FP= fopen(FileName, "rb");
    if(FP!= NULL){
        unsigned long int FilePosition;
        fseek(FP, 0, SEEK_SET);
        FilePosition=ftell(FP);
        fclose(FP);
    }
    */
    close(SD);
    return 0;
}

The Reader.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(void){
    struct MemData{
        char* FileName;
        int LastByteLength;
        int ReadPointer;
        int WritePointer;
        char Data[512000];//MEMORY BLOCK SIZE: 500 KB
    };
    int SD;
    struct MemData *M;
    int NumberOfBuffers=10;
    int BufferSize=51200;//FILE BUFFER SIZE 50 KB

    SD= shm_open("/program.shared", O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
    if(SD< 0){
        printf("\nshm_open() error \n"); 
        return EXIT_FAILURE; 
    }
    fchmod(SD, S_IRWXU|S_IRWXG|S_IRWXO); 
    if(ftruncate(SD, sizeof(MemData))< 0){
        printf ("ftruncate() error \n");
        return EXIT_FAILURE; 
    }
    //THE FOLLOWING TYPECASTING AVOIDS THE NEED TO ATTACH THROUGH shmat() in shm.h HEADER I GUESS.
    M=(struct MemData*)mmap(NULL, sizeof(MemData), PROT_READ|PROT_WRITE, MAP_SHARED, SD, 0);
    if(M== MAP_FAILED){
        printf("mmap() error");
        return EXIT_FAILURE;
    }else{
        printf("\n%s", M->FileName);
        printf("\n%d", M->LastByteLength);
        printf("\n%d", M->ReadPointer);
        printf("\n%d", M->WritePointer);
    }
    /*
    FILE *FP= fopen(FileName, "rb");
    if(FP!= NULL){
        unsigned long int FilePosition;
        fseek(FP, 0, SEEK_SET);
        FilePosition=ftell(FP);
        fclose(FP);
    }
    */
    munmap(M,sizeof(MemData));
    close(SD);
    return 0;
}

1 Ответ

2 голосов
/ 20 мая 2019

Судя по вашим комментариям, проблема связана с тем, как вы назначаете и передаете значение FileName.

M->FileName=(char*)"xaa";

В результате M->FileName держитуказатель на строку в памяти процесса записи.Разыменование этого указателя в процессе считывателя приводит к ошибке сегментации из-за того, что имя файла хранится в памяти процесса записи, которая не передается читателю.Вам нужно хранить сами символы в общей памяти, а не указатель на память процесса записи.

Если вы можете смело предположить максимальную длину строки имени файла, вы можете изменить структуру, чтобы хранить всю строку скореечем указатель: измените char* FileName; на char FileName[256]; или другое значение фиксированной длины.Вам нужно будет использовать strcpy вместо прямого назначения после внесения этого изменения: измените M->FileName=(char*)"xaa"; на strcpy(M->FileName, "xaa");.

Если вы хотите строку динамической длины, вы можете снова вызвать mmap, чтобы выделить общийпамять только для строки, а затем сохранить указатель на эту строку общей памяти в FileName.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...