Попытка создать сегмент разделяемой памяти между процессами в клиент-серверной программе - PullRequest
0 голосов
/ 27 октября 2019

Я создаю клиент-серверную программу, которая использует сокеты для подключения, как только клиент подключился к серверу, для клиента создается новый процесс (требуется для проекта). У меня есть связанный список на сервере, который хранит структуры клиентов, хранящие информацию о них.

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

node_t *client_list = NULL;

int main() {
    int shmid;
    key_t key;
    key = 1234;

    shmid = shmget(key, SHMSZ, IPC_CREAT | 0666);

    client_list = (node_t *) shmat(shmid, (void *)0, 0);

    while(1) {
        pid_t current_process;
        if ((current_process = fork()) == 0) {
            node_add(client_list, &client);
            node_print(client_list);
            pthread_create(&thread[client_count], NULL, network(client.ID), (void *) &client);

    }
    return 0;
}

(я оставил код подключения к сокету и т. Д. Отключенным, чтобы сделать его более читаемым). Возможно, я делаю что-то очень неправильное в этой текущей версии, но, насколько я понимаю, я создаю сегмент совместно используемой памяти для 'node_t * client_list', который представляет собой связанный список, а затем, после создания нового процесса из соединения, к нему добавляется клиентский узел,Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 28 октября 2019

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

Для меня есть несколько выводов:

  • mmap кажется более простой и современной реализацией разделяемой памяти, чем сегменты разделяемой памяти sysv.
  • Семафор или другое согласование требуется, чтобы убедиться, что чтение завершено, а запись - нет.
  • данные в mmap являются общими, но если эти данные являются указателями, они должныуказать на сегмент mmap, иначе он не будет работать на каждой развилке ... Я почти уверен. Поэтому обязательно поместите все ваши общие данные в общую память, а не только в ее адрес.

Замечание об использовании разделяемой памяти: я создал 2 разных mmap разделяемых памяти, одну для семафора и одну для самих данных. Но вместо этого я мог бы создать struct и поместить в него обе переменные, что, вероятно, имеет больше смысла, потому что mmap ed память должна быть выровнена по страницам, и поэтому я думаю каждая новая карта памяти требуетминимум 1 полная страница памяти. Определенно нужно подумать о том, как выставить желаемое состояние между процессами.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <semaphore.h>

#define BUFSIZE 20480

int main(int argc, char**argv){
  int protection = PROT_READ | PROT_WRITE;
  int visibility = MAP_SHARED | MAP_ANONYMOUS;
  // we need shared memory for our semaphore
  sem_t* sem = mmap(NULL, sizeof(sem_t), protection, visibility, -1, 0);
  if(sem == MAP_FAILED) {
    perror("Couldn't create memory map");
    exit(errno);
  }
  if( sem_init(sem, 1, 0) != 0 ){
    perror("couldn't init shared memory");
    exit(errno);
  }
  // now shared memory for the data we care about, which is just a string up to BUFSIZE len including termination
  void* shmem = mmap(NULL, BUFSIZE, protection, visibility, -1, 0);
  if(shmem == MAP_FAILED) {
    perror("Couldn't create memory map");
    exit(errno);
  }
  // let's make sure there's a '\0' at the end for the string functions by copying an empty string in.  
  strncpy(shmem, "" , BUFSIZE-1);
  pid_t cpid = fork();
  if(cpid < 0){
    perror("Couldn't fork");
    exit(errno);
  }
  else if( cpid == 0 ){ // child!  
    char* msg = malloc(sizeof(char)*BUFSIZE);
    *msg = '\0';
    while( strlen(msg) == 0 ){
      printf("What would you like the message to be? ");
      fflush(stdout);
      fgets(msg, BUFSIZE, stdin);
    }
    printf("%lu character string input\n", strlen(msg));
    strncpy(shmem, msg, BUFSIZE-1);
    sem_post(sem);
  }
  else {
    int sig;
    if( sem_wait(sem) ){
      perror("couldn't wait for semaphore in parent");
      exit(errno);
    }
    printf("%lu character string input\n", strlen(shmem));
  }
}

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