2015-10-23 76 views
3

我在C中有一個鏈接列表,或者我想。 的結構是:如何在共享內存的struct中分配鏈表c

//Structure of the domain list 
typedef struct domains *domain_list; 
    struct domains{ 
    char *domain; 
    domain_list next; 
}domains_node; 

//Structure of the configuration of the server 
typedef struct{ 
    int n_threads; 
    domain_list domain_list; 
    char* local_domain; 
    char* named_pipe_statistics; 
}server_config; 

我試圖在共享內存進入其中,我敢肯定,該結構是好的,但我不知道是否該鏈表是正確的(使用全局變量):

//Initialize shared memory 
if((config_shmid = shmget(IPC_PRIVATE, sizeof(server_config), IPC_CREAT|0777)) < 0){ 
    perror("Error in config shmid\n"); 
    exit(1); 
} 
if((config = (server_config*)shmat(config_shmid, NULL, 0)) == (server_config *)-1){ 
    perror("Error in config shmat\n"); 
    exit(1); 
} 

if((config_domain_shmid = shmget(IPC_PRIVATE, sizeof(struct domains), IPC_CREAT|0777)) < 0){ 
    perror("Error in domain_list config shmid\n"); 
    exit(1); 
} 
if((config->domain_list = (domain_list)shmat(config_domain_shmid, NULL, 0)) == (domain_list)-1){ 
    perror("Error in domain_list config shmat\n"); 
    exit(1); 
} 

這是過程的交際。我需要一個動態的(不固定的)鏈接列表,在一個結構中,共享內存中。 所以,我需要的是一種爲我創建的新節點分配內存空間的方式,以及如何將它們連接起來。我現在不是用malloc,但在這個問題上的答案只是作爲「足夠的分配」,我不知道它是什麼。

+0

http://stackoverflow.com/q/27218618/992406 – houssam

回答

7

你不說這個,但我猜你使用共享內存,這樣幾個過程可以訪問相同的鏈表,同時或順序。

在這種情況下,您可以創建一個共享內存段,將持有的節點加上一些控制數據池。

整個信息必須包含在該段,不過,對於其他進程才能看到它。因此,您的domain成員應該是char緩衝區,而不是指向存儲器中其他位置的字符串的指針。

所有非空節點指針的值將在池中的地址,但共享內存段可能會被映射到不同的工藝不同的地址。因此,節點不能有絕對next指針。不過,他們可以在共享節點池中保留一個相對索引。這同樣適用於名單的首腦。

在您的鏈接列表代碼中,您應該用自定義函數替換mallocfree,這些自定義函數可以獲取池中的節點或將其放回。由於游泳池的尺寸固定,因此自定義malloc可能會返回NULL,您應該檢查該尺寸。

下面的代碼實現與包含在共享存儲器段固定大小的池簡單的鏈表。它將所有可見數據保留爲相對大小,但對節點指針進行操作,對於本地迭代,您可以使用dnode。由於0是有效的池索引,因此有一個特殊值DNULL,它通過size_t來描述空指針。

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <sys/shm.h> 



typedef struct DNode DNode; 
typedef struct DList DList; 

#define MAX_DNODE 32   // Max. domain string length 
#define MAX_DLEN 64    // Max. number of list nodes 

#define DNULL (MAX_DLEN + 1) // NULL value 

struct DNode { 
    char domain[64]; 
    size_t next; 
}; 

struct DList { 
    DNode pool[MAX_DNODE];  // fixed-size space for nodes 
    size_t npool;    // used space in pool 
    size_t pfree;    // pointer to re-use freed nodes 
    size_t head;    // global list head 
}; 

DList *dlist; 

DNode *dnode_alloc(void) 
{ 
    if (dlist->pfree != DNULL) { 
     DNode *node = dlist->pool + dlist->pfree; 

     dlist->pfree = dlist->pool[dlist->pfree].next; 
     return node; 
    } else { 
     if (dlist->npool < MAX_DNODE) return &dlist->pool[dlist->npool++]; 
    } 

    return NULL; 
} 

void dnode_free(DNode *node) 
{ 
    if (node) { 
     node->next = dlist->pfree; 
     dlist->pfree = node - dlist->pool; 
    } 
} 

DNode *dnode(size_t index) 
{ 
    return (index == DNULL) ? NULL : dlist->pool + index; 
} 

DNode *dnode_next(const DNode *node) 
{ 
    return dnode(node->next); 
} 

DNode *dnode_push(size_t *head, const char *str) 
{ 
    DNode *node = dnode_alloc(); 

    if (node) { 
     strncpy(node->domain, str, sizeof(node->domain)); 
     node->next = *head; 
     *head = node - dlist->pool; 
    } 

    return node; 
} 

void dnode_pop(size_t *head) 
{ 
    if (*head != DNULL) { 
     size_t next = dlist->pool[*head].next; 

     dnode_free(&dlist->pool[*head]); 
     *head = next; 
    } 
} 



int main(int argc, char* argv[]) 
{ 
    int shmid; 

    shmid = shmget(IPC_PRIVATE, sizeof(DList), IPC_CREAT | 0660); 
    if (shmid < 0) exit(1); 

    dlist = shmat(shmid, NULL, 0); 
    if (dlist == (void *) (-1)) exit(1); 

    dlist->head = DNULL; 
    dlist->pfree = DNULL; 
    dlist->npool = 0; 

    dnode_push(&dlist->head, "Alpha"); 
    dnode_push(&dlist->head, "Bravo"); 
    dnode_push(&dlist->head, "Charlie"); 
    dnode_push(&dlist->head, "Delta"); 
    dnode_push(&dlist->head, "Echo"); 

    while (dlist->head != DNULL) { 
     puts(dnode(dlist->head)->domain); 
     dnode_pop(&dlist->head); 
    } 

    shmdt(dlist); 

    return 0; 
} 
+0

是的我使用共享內存的幾個進程來訪問它。不,我不能使用線程池。我想我每次想添加節點都必須做shmid和shmat,但這只是猜測 –

+0

它不是一個線程池,而是一個節點池。如果你真的想爲每個節點創建一個共享內存段,那麼你必須創建下一個指針'shmid's或其他東西,但在我看來這真的沒有意義。順便說一下,我已經在不同的進程(父/子和順序)上測試了上面的代碼,它工作。 –

+0

拼寫錯誤,我的不好。但是因爲我不能擁有一個固定大小的游泳池,所以我必須以另一種方式來完成 –