尝试在客户端-服务器程序中的进程之间创建共享内存段

Trying to create a shared memory segment between processes in client-server program

我正在创建一个使用套接字进行连接的客户端-服务器程序,一旦客户端连接到服务器,就会为客户端创建一个新进程(项目需要)。我在服务器中有一个链接列表,用于存储持有有关它们的信息的客户端结构。

这造成的问题是,例如,当 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' 创建共享内存段,这是一个链表,然后在从连接创建新进程后,将客户端节点添加到其中.任何帮助将不胜感激。

对这个问题有点好奇,所以我想把分叉/共享内存和信号量的概念证明放在一起,以防止读取不完整的写入。

我有一些要点:

  • mmap 似乎是比 sysv 共享内存段更简单、更现代的共享内存实现。
  • 需要信号量或其他协调来确保读取完成而写入未完成。
  • mmap 中的数据是共享的,但如果该数据是一个指针,它必须指向一个 mmap 段,否则它不会在每个 fork 中工作......我很确定。因此,请确保将您的共享数据 all 放入共享内存中,而不仅仅是其地址。

关于使用共享内存的注意事项:我创建了 2 个不同的 mmap-共享内存,一个用于信号量,一个用于数据本身。但我本可以创建一个 struct 并将两个变量放入其中,这可能更有意义,因为 mmaped 内存必须是页面对齐的,因此我 认为 每个新的内存映射至少需要 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 '[=10=]' 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 = '[=10=]';
    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));
  }
}