简体   繁体   English

共享内存段中的链接列表

[英]Linked list in a shared memory segment

I am currently working on a part where a linked list, one linked list node has multiple variable data, is to be saved in a shared memory segment so that another program can read that list and do operations accordingly. 我当前正在处理其中链接列表(一个链接列表节点具有多个变量数据)的部分要保存在共享内存段中,以便另一个程序可以读取该列表并进行相应的操作。

I have previously worked on socket programming, but sending a stream of data does not fulfill my purpose, as I have to do validation based on reading one node/element at a time. 我以前从事套接字编程,但是发送数据流无法实现我的目的,因为我必须基于一次读取一个节点/元素来进行验证。 So, of all the IPC's, I think shared memory would be the best as it also has good performance than others(in this case, not generally). 因此,在所有IPC中,我认为共享内存将是最好的,因为它还具有比其他内存更好的性能(在这种情况下,一般而言)。

The following is the struct that I have made: 以下是我制作的结构:

    struct DNode {
    char *polname;
    char *devname;
    char *status;
    char *srczone;
    char *dstzone;
    char *srcaddr;
    char *dstaddr;
    char *srcuser;
    char *app;
    char *service;
    char *urlcategory;
    char *action;
    char *vulnerability;

    char *value;
    struct DNode *next;
        };
    struct DNode *head = NULL;

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->polname, str, sizeof(node->polname));
        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 list_insert_front(struct node* new_node) {
        struct node *temp;
        temp = malloc(sizeof *temp);
        if (temp && new_node) {
            memcpy(temp, new_node, sizeof(struct node));
            temp->next = head;
            head = temp;
            return 1;
        }
        return 0;
    }

       int main(int argc, char **argv)
{
   struct Dnode *iter = head;
    int shmid;
    xmlDocPtr doc;
    xmlNode *root_element = NULL;


    if (argc != 2)
    {
        printf("\nInvalid argument\n");
        return(1);
    }

    doc = xmlReadFile(argv[1], NULL, XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
    if (doc == NULL)
    {
        fprintf(stderr, "Document not parsed successfully.\n");
        return 0;
    }

    root_element = xmlDocGetRootElement(doc);

    if (root_element == NULL)
 {
        fprintf(stderr, "empty document\n");
        xmlFreeDoc(doc);
        return 0;
    }

    printf("Root Node is %s\n", root_element->name);
    traverse_dom_trees(root_element);

    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;

    while(iter != NULL){
dnode_push(&dlist->head, head->polname);
    dnode_pop(&dlist->head);
    iter = head->next;
    }


    shmdt(dlist);
    xmlFreeDoc(doc);       // free document
    xmlCleanupParser();    // Free globals
    return 0;
}

As you can see, I have also included an XML parser part in the main function so as to give you an idea of what I am taking as an input. 如您所见,我还在主函数中包括了XML解析器部分,以使您大致了解我要作为输入的内容。 But the part where I am stuck is how to save/use this struct inside a shared memory, and making it easy for the other program to access it. 但是我遇到的问题是如何在共享内存中保存/使用此结构,并使其他程序易于访问它。

Please can somebody provide me with some pseudo-code for the same as I have never used such C functionalities before and am absolutely clueless on how to approach this. 请有人能为我提供一些伪代码,就像我以前从未使用过C函数一样,并且对于如何实现此功能绝对一无所知。 Any and all suggestions are welcome and am thankful in advance. 任何和所有建议都值得欢迎,并在此先感谢。

Edit 1 编辑1

Using Centos7 on a virtual machine since somebody pointed out that mentioning the platform would be fruitful. 因为有人指出在平台上使用Centos7会带来很多成果。

Edit 2 Just added some code to implement shared memory segments, and it does not give me any such errors. 编辑2只是添加了一些代码来实现共享内存段,它并没有给我任何这样的错误。 What my concern is: 我担心的是:

  • Is it doing what I intended? 它按照我的意图去做吗?
  • Is the approach correct? 方法正确吗?
  • I know I am currently just pushing one element but this sure is right, right? 我知道我目前只是在推动一个要素,但这肯定是正确的,对吗?
  • Am I wasting time and efforts trying to work it out using shared memory? 我是在浪费时间和精力来尝试使用共享内存吗?

You will need to: 您将需要:

  • Setup shared memory on your platform - see here . 在您的平台上设置共享内存-请参阅此处
  • In your program, call shm_open to open the shared memory and use mmap to access it using a pointer - see here . 在您的程序中,调用shm_open打开共享内存,并使用mmap通过指针访问共享内存-请参见此处
  • Accessing shared memory from different processes/thread must use some arbitration/mutual exclusion mechanism - see here . 从不同的进程/线程访问共享内存必须使用某种仲裁/互斥机制-参见此处

In general you cannot warrant that a shared memory segment will occupy the same virtual address range in one process than in other. 通常,您不能保证共享内存段在一个进程中将占据与另一个进程相同的虚拟地址范围。 So you'll have a problem when trying to interpret the values in the pointer fields, as they represent the address of the pointed object in the virtual address space of the process that wrote there the pointer value and this can be different if both processes map the shared memory segment at different places. 因此,当您尝试解释指针字段中的值时会遇到问题,因为它们表示在指针值所在的进程的虚拟地址空间中指向对象的地址,并且如果两个进程都映射,则该值可能会有所不同共享内存段在不同的位置。

You can pass the mmap call a pointer to tell the system where in your virtual address space you want the segment to be mapped, so the shared pointers point to the same place in both virtual address spaces. 您可以通过mmap调用指针来告诉系统要在虚拟地址空间中映射该段的位置,因此共享指针指向两个虚拟地址空间中的相同位置。 But that pointer is only a hint, and the operating system is not forced to follow your pointer. 但是该指针仅是一个提示,操作系统不会被迫遵循您的指针。

There are two solutions for this. 有两种解决方案。 The first is to offset the pointer values, so you construct your virtual address space pointer from the one you see in the shared segment. 第一种是偏移指针值,因此您可以从共享段中看到的指针构造虚拟地址空间指针 The second is to ensure your memory segments both are mapped to the same address. 第二个是确保您的内存段都映射到相同的地址。 This has to be coordinated between both processes (but it has to be done only once, at memory mapping) as the place that is good for one can be forbidden for the other (because it has mapped some other thing there) 这必须在两个进程之间进行协调(但在内存映射时必须只执行一次),因为一个对另一个有利的位置可能被禁止(因为它在那里映射了其他内容)

In 64bit architectures this is easy, as you have a zillion virtual addresses to map the segment to, and probably you can select an address without clashing with other subsystem. 在64位体系结构中,这很容易,因为您有数不胜数的虚拟地址可将网段映射到该地址,并且可能可以选择一个地址而不会与其他子系统冲突。 Think that in 32bit systems, normally shared libraries consume a bunch of addresses for the data segments of the modules herein, and the stacks makes provision for large amounts of memory, and the heap also... so you have to plan the thing before an attempt of putting both segments in a shared, identical address. 认为在32位系统中,通常共享的库会占用这里模块的数据段的一堆地址,而堆栈则为大量的内存提供了空间,而堆也为...提供了空间,因此您必须在部署前先进行规划。尝试将两个段都放在一个共享的相同地址中。

NOTE 注意

In your particular case, that almost all the fields of the structure are pointers, this applies to all the fields, and not only the list linking ones. 在您的特定情况下,结构的几乎所有字段都是指针,这适用于所有字段,而不仅是列表链接字段。 Not only all the list nodes must lie in the shared segment... also all the strings, and everything you access that is shared. 不仅所有列表节点都必须位于共享段中,还包括所有字符串以及共享的所有访问内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM