在C中使用共享内存的每个客户端服务器一个进程

在C中使用共享内存的每个客户端服务器一个进程,c,linux,tcp,server,mmap,C,Linux,Tcp,Server,Mmap,出于学术目的,我正在使用TCP协议创建一个“每个客户端一个进程”服务器 我使用一个全局结构,如下所示: struct keyvalue { char a[4096]; char b[4096]; }data[1000]; 我使用fork()为每个客户端创建一个子客户端 我知道每个子进程都将此结构视为父进程的精确副本,但是如果一个子进程进行了更改,其他子进程将看不到它,这是我的目标 我在谷歌上搜索了几个小时,找到的唯一合适的解决方案是mmap()

出于学术目的,我正在使用TCP协议创建一个“每个客户端一个进程”服务器

我使用一个全局结构,如下所示:

struct keyvalue
    {
        char a[4096];
        char b[4096];
    }data[1000];
我使用fork()为每个客户端创建一个子客户端

我知道每个子进程都将此结构视为父进程的精确副本,但是如果一个子进程进行了更改,其他子进程将看不到它,这是我的目标

我在谷歌上搜索了几个小时,找到的唯一合适的解决方案是mmap()

下面,我将介绍我如何尝试解决此任务:

int main ( int argc, char *argv[])
{
for(int c = 0; c < 1000 ; c++)
    {
        data[c] = mmap(NULL, sizeof(data[c]), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);

    }
.
.
.
return 0;
}

感谢您的behave,并为我糟糕的英语表示歉意。

您可以使用以下代码创建一个结构数组,该数组在多个分叉进程之间共享

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

#define MAX_LEN 10000

struct region {
        int len;
        char buf[MAX_LEN];

};

int fd;

int main(void){

        //Create shared memory
        fd = shm_open("/myregion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
        if (fd == -1)
                printf("Error: shm_open\n");

        //Expand to meet the desirable size
        if (ftruncate(fd, MAX_LEN*sizeof(struct region)) == -1)
                printf("Error: ftruncate\n");



        pid_t pid = fork();
        if (pid == 0){
                struct region * ptr = mmap(NULL, MAX_LEN*sizeof(struct region), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
                if (ptr == MAP_FAILED)
                        printf("Error\n");


                memset(ptr, 0, 50*sizeof(struct region));
                usleep(1500000);
                ptr[33].len = 42;

        }else if (pid > 0){
                struct region * ptr = mmap(NULL, MAX_LEN*sizeof(struct region), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
                if (ptr == MAP_FAILED)
                        printf("Error\n");


                usleep(1000000);
                printf("Value before: %d\n", ptr[33].len);
                usleep(1000000);
                printf("Value after: %d\n", ptr[33].len);

        }else{
                printf("Error: fork\n");
        }

        shm_unlink("/myregion");

        return 0;
}

两者的区别在于shm_open创建了一个命名共享内存,这意味着不同可执行文件中的不同进程可以映射该内存,因为它们具有结构区域定义。在第二种情况下,这是无法做到的,即共享内存是匿名的

您可以使用以下代码创建一个结构数组,该数组在多个分叉进程之间共享

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

#define MAX_LEN 10000

struct region {
        int len;
        char buf[MAX_LEN];

};

int fd;

int main(void){

        //Create shared memory
        fd = shm_open("/myregion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
        if (fd == -1)
                printf("Error: shm_open\n");

        //Expand to meet the desirable size
        if (ftruncate(fd, MAX_LEN*sizeof(struct region)) == -1)
                printf("Error: ftruncate\n");



        pid_t pid = fork();
        if (pid == 0){
                struct region * ptr = mmap(NULL, MAX_LEN*sizeof(struct region), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
                if (ptr == MAP_FAILED)
                        printf("Error\n");


                memset(ptr, 0, 50*sizeof(struct region));
                usleep(1500000);
                ptr[33].len = 42;

        }else if (pid > 0){
                struct region * ptr = mmap(NULL, MAX_LEN*sizeof(struct region), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
                if (ptr == MAP_FAILED)
                        printf("Error\n");


                usleep(1000000);
                printf("Value before: %d\n", ptr[33].len);
                usleep(1000000);
                printf("Value after: %d\n", ptr[33].len);

        }else{
                printf("Error: fork\n");
        }

        shm_unlink("/myregion");

        return 0;
}

两者的区别在于shm_open创建了一个命名共享内存,这意味着不同可执行文件中的不同进程可以映射该内存,因为它们具有结构区域定义。在第二种情况下,这是无法做到的,即共享内存是匿名的

这个结构数组应该对所有进程都可见吗?你会考虑使用pTrx吗?@ KyKAZ是的,它应该对所有的口袋都可见。因为它是一个服务器,所以每个进程(客户端)都必须能够访问此结构。我不能使用pthreads,因为它是为了学术目的,而且指令很严格。这个结构数组应该对所有进程都可见吗?你会考虑使用pTrx吗?@ KyKAZ是的,它应该对所有的口袋都可见。因为它是一个服务器,所以每个进程(客户端)都必须能够访问此结构。我不能使用pthreads,因为它是出于学术目的,而且指令很严格。在这种情况下,结构大小是多少?我的目标是创建此结构的1000个实例,以便服务器保存客户端发送的一些数据。这就是为什么我使用数据[1000]@ArisKantas将MAX_LEN更改为理想的大小。初始化不是通过变量声明完成的,而是通过ftruncate完成的。请您解释一下这个编译错误:在函数
main::serv2.c:(.text+0x310):未定义对
shm_open'collect2的引用:错误:ld返回了1退出状态add-lrt到您的gcc命令。shm_open是外部库中的一个函数。我编辑了答案以添加编译命令。@k_kat如果我有两个必须在全局结构中读/写的函数,该怎么办?既然我在main中创建了结构,他们怎么知道我在说什么?在这种情况下,结构的大小是多少?我的目标是创建此结构的1000个实例,以便服务器保存客户端发送的一些数据。这就是为什么我使用数据[1000]@ArisKantas将MAX_LEN更改为理想的大小。初始化不是通过变量声明完成的,而是通过ftruncate完成的。请您解释一下这个编译错误:在函数
main::serv2.c:(.text+0x310):未定义对
shm_open'collect2的引用:错误:ld返回了1退出状态add-lrt到您的gcc命令。shm_open是外部库中的一个函数。我编辑了答案以添加编译命令。@k_kat如果我有两个必须在全局结构中读/写的函数,该怎么办?既然我在main中创建了结构,他们怎么知道我在说什么?
int main(void){

        struct region * ptr = mmap(NULL, MAX_LEN*sizeof(struct region), PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED,-1,0);
        pid_t pid = fork();
        if (pid == 0){

                usleep(1500000);
                ptr[33].len = 42;

        }else if (pid > 0){

                usleep(1000000);
                printf("Value before: %d\n", ptr[33].len);
                usleep(1000000);
                printf("Value after: %d\n", ptr[33].len);

        }else{
                printf("Error: fork\n");
        }

        return 0;
}