我在 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,但关于这个问题的答案只是“充分分配”,我不知道它是什么。
最佳答案
你没有这么说,但我猜你使用共享内存,以便多个进程可以同时或顺序访问同一个链表。
在这种情况下,您可以创建一个共享内存段来保存节点池和一些控制数据。
但是,整个信息必须包含在该段中,以便其他进程可以看到它。因此,您的 domain
成员应该是 char
缓冲区,而不是指向内存中其他地方的字符串的指针。
所有非空节点指针值都将是池中的地址,但共享内存段可能会映射到不同进程的不同地址。因此,节点不能有绝对的next
指针。不过,他们可以在共享节点池中保留一个相对索引。这同样适用于列表的 headsm。
在您的链表代码中,您应该将 malloc
和 free
替换为获取池中节点或将其放回那里的自定义函数。因为池具有固定大小,自定义 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;
}
关于c - 如何在共享内存c中的struct内部分配链表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33293121/