共享内存中的链接列表

问题描述 投票:1回答:2

我试图将一个结构与其各自的节点推送到一个共享内存中,其中另一个程序将读取节点内容进行一些验证(只是阅读,没有修改)。链表的每个节点都包含几个变量,以及许多节点

我的结构:

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;
}

此结构使用函数list_insert_front从XML文件中获取数据并填充列表。此链接列表现在存储在共享内存中,以便更快地处理和轻松读取其他程序。

但是,我无法这样做(因为指针错误)。我能够向我的客户端发送一个易于阅读的整数数据,但是当我对列表进行相同的尝试时,会发生BAM Segmentation fault

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;
}

我意识到我可能犯了很多愚蠢的错误,比如在while循环中,以及我尝试在共享内存段中插入结构的方式,但这就是我要求你们所有人。为了帮助我为此建立一个更好的逻辑。欢迎所有建议。

c struct linked-list shared-memory
2个回答
3
投票

你展示的并不是真正的MCVE。你在结构中有13个char *成员;对于MCVE来说,3将是充足的。您还使用XML解析函数,这些函数基本上与问题相关;你可以简化很多事情。

您没有显示将在共享内存中使用该列表的任何其他进程;拥有其中一个(它只需要附加到共享内存并遍历列表,打印结果)会很有帮助。

基本观察:

  • 如果要将列表存储在共享内存中,则列表中的每个用户都需要能够查看数据,这些数据必须全部位于共享内存中。

您在信号上无法确保所有数据都在共享内存中。

你的作业如下:

(*dlist).polname = aaron.polname;

至少四项都是伪造的。首先,aaron.polname是此进程的每进程(非共享)内存中的指针。因此,指针赋值给其他进程提供了一个伪造的地址。它指向其他进程中的一些随机位置 - 或者,如果幸运的话,它指向地址空间之外的某个位置,因此它们会快速崩溃而不是缓慢崩溃。

其次,你还没有复制字符串;你只需要指定一个指针。那是个问题。

第三,您将共享内存中的所有指针指向相同的位置,以便多个条目指向相同的数据。

第四,你应该使用dlist->polname表示法。是的,你有什么工作;它不能很好地工作。检查(写,想想)dlist->next->next(*(*dlist).next).next更容易。 (如果不逐步增加,我甚至无法写出来。而且我并没有声称这在这种情况下是一个很好的表达;我只是指出使用箭头ptr->member符号而不是星形链接访问要容易得多-dot (*ptr).member。)

您必须确保共享结构中的指针指向共享内存。

您还必须确保所有进程在同一地址加载共享内存段。如果你不能这样做,那么根本就不能可靠地使用指针;您必须使用基址(共享内存段的起始地址)的偏移量。链接指针也需要小心处理。

您没有创建足够大的共享内存块。您正在使用:

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

这为一组指针创建了足够的空间,但指针没有空间指向。您似乎也想要创建链接列表,但是您只为单个元素分配足够的空间。这必须重做。共享内存必须足够大才能包含所有共享数据 - 结构和结构指向的字符串。

所以,你需要:

  1. 分配更多共享内存。
  2. 确保所有进程在同一地址加载共享内存。
  3. 确保共享内存中结构的所有数据引用都位于共享内存中的内存位置。
  4. 将字符串从进程本地内存复制到共享内存中。
  5. 确保进程之间的读/写访问权限正确同步。
  6. 使用dlist->polname而不是(*dlist).polname除非您希望被视为新手程序员。

3
投票

您不能在共享内存段中使用指针,因为它们仅在您的进程中有效。这可能是您获得段错误的原因。您可以在共享内存段中使用偏移量。

© www.soinside.com 2019 - 2024. All rights reserved.