首页 > 解决方案 > 将元素两次添加到 Linux 内核双链表中

问题描述

我正在尝试在用户空间中使用https://github.com/torvalds/linux/blob/master/include/linux/list.h中提到的 linux 内核双向链表实现,可以找到它的用户空间实现在https://gist.github.com/roychen/1710968

以下是我最初使用的代码,它工作正常:)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "list.h"

struct Node
{
    int data;
    char name[10];
    struct list_head mylist;
};

int main()
{
    LIST_HEAD(plist);

    struct Node node1 = {.data = 10, .name = "node1", .mylist = LIST_HEAD_INIT(node1.mylist)};
    struct Node node2;

    node2.data = 20;
    strcpy(node2.name, "node2");
    INIT_LIST_HEAD(&node2.mylist);

    list_add_tail(&node1.mylist, &plist);
    list_add_tail(&node2.mylist, &plist);

    struct Node* iter;

    list_for_each_entry(iter, &plist, mylist)
    {
        printf("name = %s, data = %d\n", iter->name, iter->data);
    }

    return 0;
}

上述代码的输出是

name = node1, data = 10
name = node2, data = 20

这是预期的。

现在假设我想添加node1 两次

场景一:

    list_add_tail(&node1.mylist, &plist);
    list_add_tail(&node1.mylist, &plist);

输出 1:

name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
name = node1, data = 10
... -> non-stopping loop (to infinity)

场景二:

    list_add_tail(&node1.mylist, &plist);
    list_add_tail(&node2.mylist, &plist);
    list_add_tail(&node1.mylist, &plist);

输出 2:

name = node1, data = 10 (-> just one node is added to the list instead of 3 nodes)

上面的输出表明 list.h 实现有错误,至少在它的一个函数宏中。

我不知道我们不能在链表中添加两次节点的错误在哪里。

任何想法?!:|

*****编辑***** 场景 3:

    list_add_tail(&node1.mylist, &plist);
    list_add_tail(&node2.mylist, &plist);
    list_add_tail(&node1.mylist, &plist);

    struct Node* iter;

    list_for_each_entry_reverse(iter, &plist, mylist)
    {
        printf("name = %s, data = %d\n", iter->name, iter->data);
    }

输出 3:

name = node2, data = 20
name = node1, data = 10
name = node2, data = 20
name = node1, data = 10
name = node2, data = 20
name = node1, data = 10
name = node2, data = 20
name = node1, data = 10
name = node2, data = 20
name = node1, data = 10
... -> non-stopping loop (to infinity)

标签: clinuxlinked-listlinux-kernel

解决方案


Linux 链表不支持多次添加节点。您不能将它两次添加到同一个列表中,也不能将它添加到两个不同的列表中。


推荐阅读