简体   繁体   English

共享内存中的链接列表

[英]Linked list inside shared memory

I am trying to push a struct with its respective nodes inside a shared memory where another program will be reading the node content to do some validation(just reading, no modification). 我正在尝试将一个带有各自节点的结构推入共享内存中,另一个程序将在该结构中读取节点内容以进行一些验证(仅读取,不做任何修改)。 Each node of the linked list contains several variables, and a lot of nodes as well 链表的每个节点都包含多个变量,以及许多节点

My Struct: 我的结构:

typedef 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;
    int isok;
    struct DNode *next;
} Current;
struct DNode *head = NULL;

int list_insert_front(struct DNode* new_node) {
    struct DNode *temp;
    temp = malloc(sizeof *temp);
    if (temp && new_node) {
        memcpy(temp, new_node, sizeof(struct DNode));
        temp->next = head;
        head = temp;
        return 1;
    }
    return 0;
}

This struct is using the function list_insert_front to get data from an XML file and populate the list. 该结构使用函数list_insert_front从XML文件获取数据并填充列表。 This linked list is now to be stored inside a shared memory for faster processing and easy read-ups for other programs. 现在,此链接列表将存储在共享内存中,以加快处理速度,并轻松读取其他程序。

However, I am unable to do so (because of pointer mistakes). 但是,我无法这样做(由于指针错误)。 I am able to send an integer data to my client which is easily readable, but when I try the same with the list, BAM Segmentation fault occurs. 我可以将易于读取的整数数据发送到我的客户端,但是当我对列表尝试相同的数据时,会发生BAM Segmentation fault

Main.c Main.c

int main(int argc, char **argv)
{
    Current aaron;
    Current *dlist;
    int key = 5555;
    int shmid;
    xmlDocPtr doc;
    xmlNode *root_element = NULL;
    dlist = &aaron;

    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(key, sizeof(aaron), IPC_CREAT | 0660);
    if (shmid < 0) exit (1);

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

    printf("dlist alloc\n");
    (*dlist).isok = 10;
    printf("dlist val: %d\n", (*dlist).isok);
    //This integer value is printed and read by the client, but not the linked list

    while (Current.next != NULL){
        (*dlist).polname = aaron.polname;
        (*dlist).devname = aaron.devname;
        (*dlist).status = aaron.status;
        (*dlist).srczone = aaron.srczone;
        (*dlist).dstzone = aaron.dstzone;
        (*dlist).srcaddr = aaron.srcaddr;
        (*dlist).dstaddr = aaron.dstaddr;
        (*dlist).srcuser = aaron.srcuser;
        (*dlist).app = aaron.app;
        (*dlist).service = aaron.service;
        (*dlist).urlcategory = aaron.urlcategory;
        (*dlist).action = aaron.action;
        (*dlist).vulnerability =  aaron.vulnerability;
        Current = Current.next;
    }
    printf("printing list: ");

    shmdt(dlist);
    xmlFreeDoc(doc);       
    xmlCleanupParser();    
    return 0;
}

I realise that I might have made a lot of silly mistakes, like in the while loop maybe, and the way by which I am trying to insert the struct in the shared memory segment, but that is what I ask all of you. 我意识到我可能犯了很多愚蠢的错误,例如在while循环中,以及试图将结构插入共享内存段的方式,但这就是我向大家提出的问题。 To help me build a better logic for the same. 为了帮助我建立更好的逻辑。 All suggestions are welcome. 欢迎所有建议。

You cannot use pointers in your shared memory segment because they are only valid within your process. 您不能在共享内存段中使用指针,因为它们仅在您的进程中有效。 This is likely the reason for segfaults you getting. 这可能是您遇到段错误的原因。 You could use offsets in the shared memory segment. 您可以在共享内存段中使用偏移量。

What you show is not really an MCVE. 您显示的内容并不是MCVE。 You have 13 char * members in the structure; 您在结构中有13个char *成员; 3 would be plenty for an MCVE. 3对于MCVE来说足够了。 You are also using XML parsing functions which are basically tangential to the problem; 您还使用了与该问题基本相关的XML解析函数。 you could simplify things a lot. 您可以简化很多事情。

You don't show any of the other processes that will be using the list in shared memory; 您不会在共享内存中显示将使用该列表的任何其他进程。 it would be helpful to have one of them (it need only attach to the shared memory and traverse the list, printing the results). 拥有其中之一会很有帮助(它只需附加到共享内存并遍历列表,打印结果)。

Basic obervation: 基本观察

  • If you're going to store a list in shared memory, every user of the list needs to be able to see the data, which must all be in shared memory. 如果要将列表存储在共享内存中,则列表的每个用户都必须能够查看数据,这些数据必须全部位于共享内存中。

You're signally failing to ensure that all the data is in shared memory. 您可能无法确保所有数据都位于共享内存中。

Your assignments like: 您的作业如下:

(*dlist).polname = aaron.polname;

are bogus on at least four counts. 在至少四个方面是假的。 First, aaron.polname is a pointer in this process's per-process (unshared) memory. 首先, aaron.polname是该进程的每个进程(非共享)内存中的指针。 So the pointer assignment is giving other processes a bogus address to work with. 因此,指针分配给其他进程一个虚假的地址以供使用。 It points to some random location in that other processes address space — or, if you're lucky, to some location outside their address space so they crash quickly rather than slowly. 它指向其他进程地址空间中的某个随机位置,或者,如果您很幸运,则指向其地址空间之外的某个位置,以使它们快速崩溃而不是缓慢崩溃。

Second, you haven't copied the string; 其次,您尚未复制字符串; you've simply assigned a pointer. 您只需分配了一个指针。 That's a problem. 那是个问题。

Third, you're making all the pointers in shared memory point to the same locations, so that multiple entries point at the same data. 第三,将共享内存中的所有指针都指向相同的位置,以便多个条目指向同一数据。

Fourth, you should use dlist->polname notation. 第四,您应该使用dlist->polname表示法。 Yes, what you've got works; 是的,您的作品行之有效; it doesn't work well. 效果不好。 It is easier to check (write, think of) dlist->next->next than (*(*dlist).next).next . (*(*dlist).next).next更容易检查(编写,考虑) dlist->next->next (I can't even write that without doing it incrementally. And I'm not claiming that this is a good expression in this context; I'm just pointing out that chained access is a lot easier with the arrow ptr->member notation than the star-dot (*ptr).member .) (我什至不能不加增量地编写它。我并不是在这种情况下声称这是一个很好的表达;我只是指出,使用箭头ptr->member表示法链接访问要容易ptr->member比星点(*ptr).member

You have to ensure that the pointers in the shared structure point into shared memory. 您必须确保共享结构中的指针指向共享内存。

You also have to ensure that all the processes load the shared memory segment at the same address. 您还必须确保所有进程在同一地址加载共享内存段。 If you can't do that, then you can't reliably use pointers at all; 如果无法做到这一点,那么就根本无法可靠地使用指针。 you have to use offsets from the base address (the start address of the shared memory segment). 您必须使用距基址(共享内存段的起始地址)的偏移量。 The link pointer also needs to be handled carefully. 链接指针也需要小心处理。

You are not creating a big enough chunk of shared memory. 您没有创建足够大的共享内存块。 You are using: 您正在使用:

shmid = shmget(key, sizeof(aaron), IPC_CREAT | 0660);

That creates enough space for a set of pointers, but no space for the pointers to point at. 这样就为一组指针创建了足够的空间,但没有足够的空间指向指针。 You also seem to want to create a linked list, but you're only allocating enough space for a single element. 您似乎还想创建一个链表,但是您只为单个元素分配了足够的空间。 This has to be reworked. 这必须重新设计。 The shared memory must be big enough to contain all the shared data — the structures and the strings that the structures point at. 共享内存必须足够大以包含所有共享数据-结构和结构所指向的字符串。

So, you need to: 因此,您需要:

  1. Allocate more shared memory. 分配更多的共享内存。
  2. Ensure that all processes load the shared memory at the same address. 确保所有进程在同一地址加载共享内存。
  3. Ensure that all the data references from the structures in shared memory are to memory locations also in shared memory. 确保共享内存中来自结构的所有数据引用都指向共享内存中的存储位置。
  4. Copy strings out of process local memory into shared memory. 将字符串从进程本地内存中复制到共享内存中。
  5. Ensure that read/write access is properly synchronized between processes. 确保进程之间的读/写访问已正确同步。
  6. Use dlist->polname and not (*dlist).polname unless you wish to be taken to be a neophyte programmer. 除非您希望成为一名新手程序员,否则请使用dlist->polname而不是(*dlist).polname

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

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