共享内存中指针数组

3

我对共享内存posix比较陌生,因此在进行一些基础工作时遇到了困难。

我有一些如下所示的节点:

typedef struct Node{
    int node_id;
    int process_id;
    struct Node* next;
}Entry;

我创建了一个指针数组,每个位置都可以有一个链表。它作为哈希表运行,并且有两个正在编辑它的进程。
因此,数组的每个位置都有元素的机会,但也可能有很多空元素。
我已经将指针数组放入共享内存中,而不是列表节点。所以这是一个大问题,因为进程1的节点对进程2不可见,反之亦然,正如下面所示。
int shmid = shmget(ftok("./main.c", 30), (size_t)(node_num*sizeof(Entry *)), 0666 | IPC_CREAT);
if(shmid == -1){
    fprintf(stderr, "shmget error");
    exit(EXIT_FAILURE);
}
void* shared_memory = (void*)shmat(shmid, (void*)0, 0);
if(shared_memory == (void*)-1){
    frpintf(stderr, "shmat error");
    exit(EXIT_FAILURE);
}
Entry** HashTable = (Entry **)shared_memory;

这个表将插入和删除节点的两个过程结合在一起。我看到了一个解决方案,但它要求列表具有固定的大小,其中池中的所有节点都在共享段内,但在我的情况下,它不是固定的,因为数字是在执行期间作为参数给出的。
我的数组作为哈希表,并且可以放置的项目受到限制,所以让我担心的是:
1. 我将不得不从一开始就在段中放置X个节点并通过哈希函数连接它们。 2. 如果我使用shmget和nodes_num*sizeof(Entry)作为参数来创建它们,我应该如何分配它们?因为我认为指针数组在实现中扮演着重要角色,因为很多指针是空的。
那么,在共享内存段中实现这个哈希表的最佳方法是什么?
编辑#1
评论给了我一个想法,但我仍然不知道它是否是一个好的实现。
我的想法是保留我已经有的指针数组,并在共享内存中添加另一个数组,大小为nodes_num;,然后使第一个数组指向第二个包含所有数据(节点)的数组的特定位置。
int shmid2 = shmget(ftok("./main.c", 30), (size_t)(node_num*sizeof(Entry )), 0666 | IPC_CREAT);
if(shmid2 == -1){
    fprintf(stderr, "shmget error");
    exit(EXIT_FAILURE);
}
void* shared_memory2 = (void*)shmat(shmid, (void*)0, 0);
if(shared_memory2 == (void*)-1){
    frpintf(stderr, "shmat error");
    exit(EXIT_FAILURE);
}
Entry* Data = (Entry *)shared_memory2;

你需要将实际节点放入共享内存中,然后每个节点内的指针也将指向共享内存。 - Iłya Bursov
我很想这样做,但事实是我找不到方法。我遇到了很多问题。 - Theo.Fanis
我不明白为什么你想要一个指针数组。一个 Entry 数组应该就足够了。 - user58697
@user58697 我认为这是不够的。一个 Entry 数组意味着在数组的每个位置上我都有一个 entry 项。我的数组是一个带有列表的哈希表,因此有些位置根本没有元素,而其他位置则有多个元素。 - Theo.Fanis
1
void* shared_memory2 = (void*)shmat(shmid, (void*)0, 0); 返回的指针可能因为不同进程附加到该内存段而不同。在这种情况下,“->next”指针可能会指向创建进程所拥有的地址范围之外。在shm(或(mmapped)文件)中存储指针是没有意义的。您应该存储索引或偏移量,而不是指针。 - wildplasser
1个回答

0

主要使用共享内存进行进程间通信。这意味着您可以将一些数据放入内存中,另一个进程将获取该数据。

因此,您可以在共享内存中附加指针数组,并在另一个进程中获取所有指针,但两个进程具有不同的堆栈,因此进程1在该位置具有不同的数据,而进程2在其自己的堆栈中具有不同的数据。

例如,您正在共享进程1上的1000位置的一个指针位置“hello”,则您将1000位置共享到另一个进程,而另一个进程转到1000位置并读取该位置的数据,然后您将获得分段错误,因为在您要搜索的位置上没有任何内容。

希望您理解这件事。如果您的情况不同,请将其设置为NULL(void)。谢谢。

我还在共享内存中创建了数据结构,如果您正在寻找它,请告诉我,我会向您展示方法。

您可以像这样传递指针

char **array;
char *shared_memory;
int i=0;
array = (char **)shmat(shmid, (void*)0, 0);
shared_memory = (char *)shmat(shmid, (void*)0, 0);
array[i] = shared_memory;

同样,您可以将所有指针输入到指针数组中。如果您打印所有指针的位置,那么您将得到相同的结果。

而且您可以这样访问:

int j=0;
fprintf(stdout,"%d",get_data[j++]->node_id);

这是完整的代码:

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>

typedef struct Node{
    int node_id;
    int process_id;
    struct Node* next;
}entry;

entry **array;
int shmid;
static int i=0;

void add_begin(entry **hptr_get){

fprintf(stdout,"in add_begin\n");

entry* shared_memory = (entry *)shmat(shmid, (void*)0, 0);
if(shared_memory == (void*)-1){
    fprintf(stdout,"shmat error");
    exit(0);
}
array[i++] = shared_memory;

shared_memory->node_id = 1;
shared_memory->process_id = 1;

shared_memory->next = *hptr_get;
*hptr_get = shared_memory;
}

void print(entry **print_data){
int j=1;
while(print_data[j]){

    fprintf(stdout,"%d",print_data[j]->node_id);
    fprintf(stdout,"%d",print_data[j]->process_id);
    print_data[j++];
 }
}

int main(){

int node_num = 10;
key_t key;
key = 4567;
char ans;

   shmid = shmget(key, (size_t)(node_num*sizeof(entry)),0666|IPC_CREAT);
  if(shmid == -1){
    fprintf(stderr,"shmget error");
    exit(0);
 }

array = (entry **)shmat(shmid, (void*)0, 0);

entry *hptr = (entry *)shmat(shmid, (void*)0, 0);

 array[i++]=hptr;

hptr = 0;

do{
    add_begin(&hptr);
    fprintf(stdout,"Do you want to add another data in shared memory?(Y/N)\n");
    fscanf(stdin," %c",&ans);
   }while((ans=='y')||(ans=='Y'));
 array[++i] = 0;
 print(array);
 }

我知道这种情况正在发生。我想保留指针数组,并且将所有数据放在共享段中。问题是我不知道该怎么做。 - Theo.Fanis
请参考我编辑过的答案,它可能会对你有所帮助。但是我建议你不要走这条路,如果你的另一个进程需要数据,那么将数据本身放入共享内存而不是指针,并向另一个进程发送信号,这样你的另一个进程就会处理该信号并进入共享内存获取特定的数据并进行进一步的工作。我曾经处于你现在所处的相同情况,但我更喜欢通过这种方式来解决这个问题。 - cdhaval

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接