在单个应用程序中,hash、链表等结构通过指针来串接节点,但是在多个程序间因为地址空间不同,无法通过指针来定位。我们利用共享内存地址连续的特点,将连续的共享内存看做是一个节点数组,然后通过数组下表来定位节点。这样就能实现在多个程序间利用共享内存实现链表、HASH等数据结构。
C语言实现的容器类型如链表、HASH、队列等,一般都是通过指针将多个节点链接起来。如HASH结构一般如下定义:
typedef struct hash_node
{
int value;
struct hash_node *next;
}hash_node_t;
typedef struct hash_table
{
int counter;
struct hash_node *head[5];
}hash_table_t;
表结构如下图:
hash_table通过指针指向hash_node,hash_node也是通过指针指向其他hash_node。在一个程序中实现都没问题,但在两个进程中他们的地址空间是不一样的,如指向同一块共享内存空间的指针shm
int shmid;//共享内存标识符
key_t key = ftok("/tmp", 1);
if (-1 == key)
{
printf("ftok failed\n");
return -1;
}
shmid = shmget(key, HASH_TABLE_SIZE, 0666|IPC_CREAT);
if(shmid == -1)
{
printf("ftok failed\n");
return -1;
}
void *shm = shmat(shmid, 0, 0);
虽然指向同一块内存空间,但是他们的指针值不同,显然在A进程中设置的指针无法在B进程中使用,同样在hash_node_t中的next指针是指向下一个node节点,但是该指针在另外进程中算野指针,也无法使用。所以用指针实现的hash、链表等结构无法在不同程序中使用。
使用指针是为了找到下一个节点的位置,另外共享内存的分配到的空间都是连续的,所以相对未知都是固定的,结合这两点,我们可以将共享内存看做一个数组,然后用数组下标代替原来的指针查找节点。
将hash_node节点结构改成
typedef struct hash_node
{
int value;
int next;
}hash_node_t;
typedef struct hash_table
{
int count;
int head[5];
}hash_table_t;
对于hash表,共享内存有两块,一块是hash_table,一块是hash_node_t的节点池
如上图,假设在程序A中head[1]的值是2,即其指向的节点是hash_node[2],hash_node的next值是0,即它的下一个节点是hash_node[0],代码如下:
在程序B中:
//获取hash表的位置
hash_table_t *hash_table = (hash_table_t*)shm1;
//head[2]的值
int index = hash_table->head[1];
//获取node节点的未知
hash_node_t*hash_node = (hash_node_t*)shm2;
//head[1]的第一个节点即为hash_node[index]
//hash_node[index]下一个节点
int next = hash_node[index].next;