Dynami c Распределение двумерного массива ОБЩАЯ с mmap - PullRequest
2 голосов
/ 16 марта 2020

Я пытаюсь отобразить разделяемую память или выделить ее в существующую разделяемую память, используя сопоставление файлов разделяемой памяти, используя mmap.

Первая обнаруженная проблема - использование mallo c и mmap в circular_buf_init функция. Я думаю, что malloc не распределяется между процессами, и я нашел реализацию MAP_ANONYMOUS временным решением.

Я использую эту структуру и ее функции:

struct circular_buf_t
{
    char **buffer;
    size_t head;
    size_t tail;
    size_t max; //of the buffer
    bool full;
};

cbuf_handle_t circular_buf_init(cbuf_handle_t cbuf, size_t size)
{
    //cbuf_handle_t cbuf //= malloc(sizeof(circular_buf_t));

    assert(cbuf);
  //size_t cb = sizeof(char *) * size;

  /* cbuf->buffer = (char **)malloc(sizeof(char *) * size);
  for(int i = 0; i < size; i++){
    cbuf->buffer[i] = (char *)malloc(sizeof(char) * 256);
  } */

  cbuf->buffer = (char **)mmap(cbuf->buffer, sizeof(char *) * size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  for(int i = 0; i < size; i++){
    cbuf->buffer[i] = (char *)mmap(cbuf->buffer[i], sizeof(char) * 256, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  }

  if (cbuf->buffer == MAP_FAILED)
        exit(EXIT_FAILURE);

    cbuf->max = size;
    circular_buf_reset(cbuf);

    assert(circular_buf_empty(cbuf));

  printf("sizeof(cbuf)=%zu\n",sizeof(cbuf));

    return cbuf;
}

void advance_pointer(cbuf_handle_t cbuf)
{

    if (cbuf->full)
    {
        cbuf->tail = (cbuf->tail + 1) % cbuf->max;
    }

    cbuf->head = (cbuf->head + 1) % cbuf->max;

    // We mark full because we will advance tail on the next time around
    cbuf->full = (cbuf->head == cbuf->tail);
}

int circular_buf_put(cbuf_handle_t cbuf, char *data)
{
    int r = -1;

    if (!circular_buf_full(cbuf))
    {
        //cbuf->buffer[cbuf->head] = (char *)malloc(sizeof(char) * 256);
        strcpy(cbuf->buffer[cbuf->head], data);
        advance_pointer(cbuf);
        r = 0;
    }

    return r;
}

void print_buffer_status(cbuf_handle_t cbuf)
{
    printf("Full: %d, empty: %d, size: %zu\n",
           circular_buf_full(cbuf),
           circular_buf_empty(cbuf),
           circular_buf_size(cbuf));
}

void circular_buf_reset(cbuf_handle_t cbuf)
{
    cbuf->head = 0;
    cbuf->tail = 0;
    cbuf->full = false;
}

size_t circular_buf_size(cbuf_handle_t cbuf)
{
    size_t size = cbuf->max;

    if (!cbuf->full)
    {
        if (cbuf->head >= cbuf->tail)
        {
            size = (cbuf->head - cbuf->tail);
        }
        else
        {
            size = (cbuf->max + cbuf->head - cbuf->tail);
        }
    }

    return size;
}

size_t circular_buf_capacity(cbuf_handle_t cbuf)
{
    assert(cbuf);

    return cbuf->max;
}



int circular_buf_get(cbuf_handle_t cbuf, char * data)
{
    int r = -1;

    if(!circular_buf_empty(cbuf))
    {
        strcpy(data,cbuf->buffer[cbuf->tail]);
        retreat_pointer(cbuf);

        r = 0;
    }

    return r;
}

bool circular_buf_empty(cbuf_handle_t cbuf)
{
    return (!cbuf->full && (cbuf->head == cbuf->tail));
}

bool circular_buf_full(cbuf_handle_t cbuf)
{
    return cbuf->full;
}

В моем program

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <stdbool.h>
#include <unistd.h>
#include <getopt.h>
#include "../circular_buffer/circular_buffer.h"
#include "../circular_buffer/circular_buffer.c"
#include "../shared/shared.h"

int main(int argc, char *argv[])
{
  int opt, val;
  size_t buffer_size;
  char *buffer_name;

  buffer_size = 0;
  while ((opt = getopt(argc, argv, "s:n")) != -1)
  {
    switch (opt)
    {
    case 'n':
      buffer_name = strdup(argv[optind]);
      break;
    case 's':
      buffer_size = atoi(optarg);
      break;
    default:
      fprintf(stderr, "Usage: %s [-n buffer_name] [-s buffer_size]\n",
              argv[0]);
      exit(EXIT_FAILURE);
    }
  }

  if (optind >= argc)
  {
    fprintf(stderr, "Expected argument after options\n\tUsage: %s [-n buffer_name] [-s buffer_size]\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  printf("buffer_name argument = %s\n", buffer_name);
  printf("buffer_size argument = %zu\n", buffer_size);
  //create the shared memory segment
  buffer_shm_fd = shm_open(buffer_name, O_CREAT | O_RDWR, 0666);
  //configure the size of the shared memory segment
  size_t len = sizeof(struct circular_buf_t); //+ sizeof(char *) * buffer_size * sizeof(char) * 256;
  ftruncate(buffer_shm_fd, len);

  //map the shared memory segment in process address space
  //circular_buf_init(buffer_mem_ptr, buffer_size);

  buffer_mem_ptr = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, buffer_shm_fd, 0);



  circular_buf_init(buffer_mem_ptr, buffer_size);

  printf("sizeof(buffer_mem_ptr) = %zu\n",sizeof(buffer_mem_ptr));
  //printf("cb=%zu\n",cb);
  printf("4096=%zu\n",4096);
  char *s = "datos";
    circular_buf_put(buffer_mem_ptr, s);
    print_buffer_status(buffer_mem_ptr);

  /* char data[256];
            circular_buf_get(buffer_mem_ptr, data);
            printf("%s ", data); */

  //

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


  free(buffer_name);


  exit(EXIT_SUCCESS);
}

И второй процесс использования общей памяти - это

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <stdbool.h>
#include <unistd.h>
#include "../shared/shared.h"
#include "../circular_buffer/circular_buffer.h"
#include "../circular_buffer/circular_buffer.c"

int main()
{
  const char *name = "k";
  int shm_fd; //shared memory file discriptor
  int buffer_size = 3;
  size_t len = sizeof(struct circular_buf_t); //+ sizeof(char *) * buffer_size * sizeof(char) * 256;

  /* make * shelf shared between processes*/
  //create the shared memory segment
  shm_fd = shm_open(name, O_RDWR, 0666);
  //configure the size of the shared memory segment
  ftruncate(shm_fd, len);
  //map the shared memory segment in process address space
  buffer_mem_ptr = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
  buffer_mem_ptr->buffer = (char **)mmap(buffer_mem_ptr->buffer, sizeof(char *) * buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  for(int i = 0; i < buffer_size; i++){
    buffer_mem_ptr->buffer[i] = (char *)mmap(buffer_mem_ptr->buffer[i], sizeof(char) * 256, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  }

  /* creat/open semaphores*/
  //cook post semaphore fill after cooking a pizza

  print_buffer_status(buffer_mem_ptr);
  printf("\nCook: I have started cooking pizza.\n");


char *s = "datos";
    circular_buf_put(buffer_mem_ptr, s);
    print_buffer_status(buffer_mem_ptr);

    char data[256];
            circular_buf_get(buffer_mem_ptr, data);
            printf("%s ", data);
    /* char *s = "datos";
    circular_buf_get(buffer_mem_ptr, s);
    print_buffer_status(buffer_mem_ptr); */



  return 0;
}

Но я понятия не имею, как распределить это динамическое c 2d выделение массива для разделяемой памяти, используя ММАП. Пожалуйста, дайте мне обратную связь, чтобы помочь найти решение.

...