2017-04-25 13 views
1

我正在创建一个“每进程一个进程”服务器使用TCP协议进行学术目的。每个客户端服务器在C中使用共享内存的一个进程

我用一个全球性的结构像一个波纹管:

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; 
} 

”不要理解这个函数的用法,文档对这个项目没有帮助。

如果有人向我解释为我的项目使用此功能的确切方式,那将会很棒。 编辑:

这种全球性的结构是使用两个全局函数:

void put(char *key, char *value) 
{ 
. 
. 
.  
strcpy(data[lp].keys,key); 
strcpy(data[lp].values,value); 
. 
. 
. 
} 

感谢您的行为和我的英语不好对不起。

+0

这个结构数组应该对所有进程都可见?你会考虑使用pthreads吗? –

+0

@k_kaz是的,它应该对所有的过路者都是可见的。因为它是一个服务器,所以每个进程(客户)必须有权访问这个结构。我不能使用pthreads,因为它是为了学术目的,并且指令是严格的。在这种情况下 –

回答

0

您可以使用下面的一段代码创建一个跨多个分叉进程共享的结构数组。

#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; 
} 

编译:gcc -o shmem_test shmem_test.c -lrt

编辑:如果你不能使用的shm_open,或者你可以做以下的在你的主要功能:

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; 
} 

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

+0

什么是结构大小?我的目标是创建1000个此结构实例,以便服务器保存客户端发送的一些数据。这就是为什么我使用数据[1000] –

+0

@ArisKantas将MAX_LEN更改为所需的大小。初始化不是通过变量声明来完成的,而是通过ftruncate –

+0

你可以请我这个编译错误: 在main函数中: serv2.c :(.text + 0x310):undefined指向'shm_open' collect2:错误:ld返回1退出状态 –

相关问题