2016-05-02 8 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

Readコードの 'ini()'の 'strcpy(dog-> nombre、"); 'で' NULL'を間接的に指定すると、セグメンテーションフォルトが発生する可能性が大きくなります。 'dog'を使う前に、いくつかのメモリを割り当ててポインタを割り当てます。 – MikeCAT

+0

注:[あなたは 'malloc()'の結果をCでキャストすべきではないと言います(http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc)。 – MikeCAT

+0

既存の変数のアドレスを 'mmap()'の引数として与えることはできません。そのアドレスはすでに非共有メモリに使用されています。共有することはできません。 – Barmar

答えて

1

あなたは、通常のファイルを作成し、それに書き込み、その後の引数としてそのファイル記述子を使用しようとしているように見えますmmap

あなたが本当にやりたいことは(私は思うが)2つのプロセス間の単純な共有メモリです。

POSIXシステムは、その目的でshm_openを提供します。

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

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

注:NULLがアドレスとして渡されます。私たちは、カーネルに、自分自身を指示しようとするのではなく、メモリを見つける場所を決定させます。これはほとんどの場合です。

Mmapが実際のメモリを指していない場合は、プロセスにを物理メモリにマッピングします。あなたのリーダーと作家は2つの異なるポインタで終わるでしょうが、彼らは同じ物理的な記憶に話しています。

完了したらshm_unlinkを忘れないでください。

関連する問題