2017-04-25 8 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退出狀態 –

相關問題