2016-05-02 3 views
-1

Я пытаюсь создать массив структур с использованием связанного списка для записи и чтения их в mmap. При попытке прочитать данные массива возникает ошибка сегментации.обмен массивом структур с использованием mmap с использованием дескриптора файла

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

Написать код:

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

struct dogType 
    { 
    char nombre[32]; 
    int edad; 
    char raza[16]; 
    int estatura; 
    float peso; 
    char sexo; 
    }; 

struct dogType *dog; 

struct test_struct 
{ 
    struct dogType dog; 
    struct test_struct *next; 
}; 

struct node 
{ 
    struct test_struct *head; 
    struct test_struct *curr; 
}; 

struct node nodes[10]; 
struct node *map; 

int i; 
long counter = 0; 

struct test_struct* add_to_list(struct dogType *pet, bool add_to_end, int hashnumber); 

void ini(void) 
{ 

    strcpy(dog->nombre, ""); 
      dog->edad = 0; 
      strcpy(dog->raza, ""); 
      dog->estatura = 0; 
      dog->peso = 0; 
      dog->sexo = ' '; 

    for(i = 0; i < 10; i++) 
    { 
     add_to_list(dog, false, i); 
    } 
} 


struct test_struct* create_list(struct dogType *pet, int hashnumber) 
{ 
    struct test_struct *ptr = (struct test_struct*)malloc(sizeof(struct test_struct)); 

    if(NULL == ptr) 
    { 
    printf("\n Node creation failed \n"); 
    return NULL; 
    } 
    ptr->dog = *pet; 
    ptr->next = NULL; 

    map[hashnumber].head = map[hashnumber].curr = ptr; 
    return ptr; 
} 



struct test_struct* add_to_list(struct dogType *pet, bool add_to_end, int hashnumber) 
{ 

    if(NULL == (map[hashnumber].head)) 
    { 
    return (create_list(pet, hashnumber)); 
    } 

    struct test_struct *ptr = (struct test_struct*)malloc(sizeof(struct test_struct)); 
    if(NULL == ptr) 
    { 
    printf("\n Node creation failed \n"); 
    return NULL; 
    } 

    ptr->dog = *pet; 
    ptr->next = NULL; 

    if(add_to_end) 
    { 
    map[hashnumber].curr->next = ptr; 
    map[hashnumber].curr = ptr; 
    } 
    else 
    { 
    ptr->next = map[hashnumber].head; 
    map[hashnumber].head = ptr; 
    } 

    counter++; 
    return ptr; 
} 

struct test_struct* search_in_list(char * name, struct test_struct **prev, int hashnumber) 
{ 
    struct test_struct *ptr = map[hashnumber].head; 
    struct test_struct *tmp = NULL; 
    bool found = false; 

    printf("\n Searching the list for value [] \n"); 

    while(ptr != NULL) 
    { 
     char *asd=ptr->dog.nombre; 
     if(strcmp(asd, name) == 0) 
    { 
     found = true; 
     break; 
    } 
    else 
    { 
     tmp = ptr; 
     ptr = ptr->next; 
    } 
    } 

    if(true == found) 
    { 
    if(prev) 
     *prev = tmp; 
    return ptr; 
    } 
    else 
    { 
    return NULL; 
    } 
} 


int delete_from_list(char * name, int hashnumber) 
{ 
    struct test_struct *prev = NULL; 
    struct test_struct *del = NULL; 

    del = search_in_list(name, &prev, hashnumber); 
    if(del == NULL) 
    { 
    return -1; 
    } 
    else 
    { 
    if(prev != NULL) 
     prev->next = del->next; 

    if(del == map[hashnumber].curr) 
    { 
     map[hashnumber].curr = prev; 
    } 
    else if(del == map[hashnumber].head) 
    { 
     map[hashnumber].head = del->next; 
    } 
    } 

    free(del); 
    del = NULL; 
    counter--; 

    return 0; 
} 

void print_list(int hashnumber) 
{ 
    struct test_struct *ptr = map[hashnumber].head; 

    printf("\n -------Printing list Start------- \n"); 
    while(ptr != NULL) 
    { 
    printf 
    ("\n%s%s", "Nombre: ", ptr->dog.nombre); 

    ptr = ptr->next; 
    } 
    printf("\n -------Printing list End------- \n"); 

    return; 
} 

void main(void) 
{ 

    map = nodes; 
    dog = malloc(sizeof (struct dogType)); 
    ini(); 

     strcpy(dog->nombre, "perrito"); 
     dog->edad = 15; 
     strcpy(dog->raza, "chanda"); 
     dog->estatura = 15; 
     dog->peso = 15; 
     dog->sexo = 'm'; 

    char *filepath = "temp.dat"; 

    int fd = open(filepath, O_RDWR | O_CREAT , (mode_t)0600); 

    if (fd == -1) 
    { 
    perror("Error opening file for writing"); 
    exit(EXIT_FAILURE); 
    } 

    size_t textsize = sizeof(nodes); 

    if (lseek(fd, textsize-1, SEEK_SET) == -1) 
    { 
    close(fd); 
    perror("Error calling lseek() to 'stretch' the file"); 
    exit(EXIT_FAILURE); 
    } 

    if (write(fd, "", 1) == -1) 
    { 
    close(fd); 
    perror("Error writing last byte of the file"); 
    exit(EXIT_FAILURE); 
    } 

    map = mmap(nodes, sizeof(nodes), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
    if (map == MAP_FAILED) 
    { 
    close(fd); 
    perror("Error mmapping the file"); 
    exit(EXIT_FAILURE); 
    } 


    add_to_list(dog, false, 1); 
    print_list(1); 

    if (msync(map, sizeof(nodes), MS_SYNC) == -1) 
    { 
    perror("Could not sync the file to disk"); 
    } 

    if (munmap(map, sizeof(nodes)) == -1) 
    { 
    close(fd); 
    perror("Error un-mmapping the file"); 
    exit(EXIT_FAILURE); 
    } 

    close(fd); 
} 

Читать код:

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

struct dogType 
{ 
    char nombre[32]; 
    int edad; 
    char raza[16]; 
    int estatura; 
    float peso; 
    char sexo; 
}; 

struct dogType *dog; 

struct test_struct 
{ 
    struct dogType dog; 
    struct test_struct *next; 
}; 

struct node 
{ 
    struct test_struct *head; 
    struct test_struct *curr; 
}; 

struct node nodes[10]; 
struct node *map; 

int i; 
long counter = 0; 

struct test_struct* add_to_list(struct dogType *pet, bool add_to_end, int hashnumber); 


void ini(void) 
{ 
    strcpy(dog->nombre, ""); 
    dog->edad = 0; 
    strcpy(dog->raza, ""); 
    dog->estatura = 0; 
    dog->peso = 0; 
    dog->sexo = ' '; 

    for(i = 0; i < 10; i++) 
    { 

     add_to_list(dog, false, i); 
    } 
} 


struct test_struct* create_list(struct dogType *pet, int hashnumber) 
{ 
    struct test_struct *ptr = (struct test_struct*)malloc(sizeof(struct test_struct)); 

    if(NULL == ptr) 
    { 
    printf("\n Node creation failed \n"); 
    return NULL; 
    } 
    ptr->dog = *pet; 
    ptr->next = NULL; 

    map[hashnumber].head = map[hashnumber].curr = ptr; 
    return ptr; 
} 



struct test_struct* add_to_list(struct dogType *pet, bool add_to_end, int hashnumber) 
{ 

    if(NULL == (map[hashnumber].head)) 
    { 
    return (create_list(pet, hashnumber)); 
    } 

    struct test_struct *ptr = (struct test_struct*)malloc(sizeof(struct test_struct)); 
    if(NULL == ptr) 
    { 
    printf("\n Node creation failed \n"); 
    return NULL; 
    } 

    ptr->dog = *pet; 
    ptr->next = NULL; 

    if(add_to_end) 
    { 
    map[hashnumber].curr->next = ptr; 
    map[hashnumber].curr = ptr; 
    } 
    else 
    { 
    ptr->next = map[hashnumber].head; 
    map[hashnumber].head = ptr; 
    } 

    counter++; 
    return ptr; 
} 

struct test_struct* search_in_list(char * name, struct test_struct **prev, int hashnumber) 
{ 
    struct test_struct *ptr = map[hashnumber].head; 
    struct test_struct *tmp = NULL; 
    bool found = false; 

    printf("\n Searching the list for value [] \n"); 

    while(ptr != NULL) 
    { 
     char *asd=ptr->dog.nombre; 
     if(strcmp(asd, name) == 0) 
    { 
     found = true; 
     break; 
    } 
    else 
    { 
     tmp = ptr; 
     ptr = ptr->next; 
    } 
    } 

    if(true == found) 
    { 
    if(prev) 
     *prev = tmp; 
    return ptr; 
    } 
    else 
    { 
    return NULL; 
    } 
} 


int delete_from_list(char * name, int hashnumber) 
{ 
    struct test_struct *prev = NULL; 
    struct test_struct *del = NULL; 

    del = search_in_list(name, &prev, hashnumber); 
    if(del == NULL) 
    { 
    return -1; 
    } 
    else 
    { 
    if(prev != NULL) 
     prev->next = del->next; 

    if(del == map[hashnumber].curr) 
    { 
     map[hashnumber].curr = prev; 
    } 
    else if(del == map[hashnumber].head) 
    { 
     map[hashnumber].head = del->next; 
    } 
    } 

    free(del); 
    del = NULL; 
    counter--; 

    return 0; 
} 

void print_list(int hashnumber) 
{ 
    struct test_struct *ptr = map[hashnumber].head; 

    printf("\n -------Printing list Start------- \n"); 
    while(ptr != NULL) 
    { 
    printf 
    ("\n%s%s", "Nombre: ", ptr->dog.nombre); 

    ptr = ptr->next; 
    } 
    printf("\n -------Printing list End------- \n"); 

    return; 
} 

void main(void) 
{ 

    ini(); 

    dog = malloc(sizeof (struct dogType)); 
    strcpy(dog->nombre, "perrito"); 
    dog->edad = 15; 
    strcpy(dog->raza, "chanda"); 
    dog->estatura = 15; 
    dog->peso = 15; 
    dog->sexo = 'm'; 

    const char *filepath = "temp.dat"; 

    int fd = open(filepath, O_RDONLY, (mode_t)0600); 

    if (fd == -1) 
    { 
    perror("Error opening file for writing"); 
    exit(EXIT_FAILURE); 
    }   

    struct stat fileInfo = {0}; 

    if (fstat(fd, &fileInfo) == -1) 
    { 
    perror("Error getting the file size"); 
    exit(EXIT_FAILURE); 
    } 

    if (fileInfo.st_size == 0) 
    { 
    fprintf(stderr, "Error: File is empty, nothing to do\n"); 
    exit(EXIT_FAILURE); 
    } 

    printf("File size is %ji\n", (intmax_t)fileInfo.st_size); 

    struct node *map = mmap(nodes, fileInfo.st_size, PROT_READ, MAP_SHARED, fd, 0); 

    if (map == MAP_FAILED) 
    { 
    close(fd); 
    perror("Error mmapping the file"); 
    exit(EXIT_FAILURE); 
    } 

    print_list(3); 

    if (munmap(map, fileInfo.st_size) == -1) 
    { 
    close(fd); 
    perror("Error un-mmapping the file"); 
    exit(EXIT_FAILURE); 
    } 

    close(fd); 
} 
+2

Выделение 'NULL' в' strcpy (dog-> nombre, ""); 'in' ini() 'в коде Read создаст большой шанс вызвать Segmentation Fault. Выделите некоторую память и назначьте ей указатель перед использованием 'dog'. – MikeCAT

+0

Примечание: Говорят [вы не должны указывать результат 'malloc()' in C] (http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – MikeCAT

+0

Вы не можете указать адрес существующей переменной в качестве аргумента 'mmap()'. Этот адрес уже используется для не-разделяемой памяти, вы не можете сделать его доступным. – Barmar

ответ

1

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

Что вы действительно хотите сделать (я думаю), просто обмениваются памятью между двумя процессами.

POSIX-системы обеспечивают для этой цели shm_open.

int fd = shm_open("/dog_storage", oflags, mode); 

pointer = mmap(NULL, length, prot, mmap_flags, fd, offset); 

Примечание NULL передается как адрес. Мы позволяем ядру решать, где найти память, а не пытаться диктовать ее сами. Это почти всегда так.

Mmap не указывает на реальную память, это дает вашему процессу отображение в физическую память. Таким образом, ваш читатель и писатель будет иметь два разных указателя, но они будут разговаривать с одной и той же физической памятью.

И не забудьте до shm_unlink, когда вы закончите.

Смежные вопросы