c - linux内核哈希表实现中双指针的使用

标签 c linux linux-kernel

我正在尝试了解链表和哈希表的 Linux 内核实现。实现的链接是 here .我了解链表实现。但我对为什么在 hlist (**pprev) 中使用双指针感到困惑。 hlist 的链接是 here .我知道 hlist 用于哈希表的实现,因为列表的头部只需要一个指针并且可以节省空间。为什么不能使用单指针完成(就像链表一样*prev)?请帮助我。

最佳答案

原因可以在其中一条评论中找到:

 547/*
 548 * Double linked lists with a single pointer list head.
 549 * Mostly useful for hash tables where the two pointer list head is
 550 * too wasteful.
 551 * You lose the ability to access the tail in O(1).
 552 */

如果您使用 *prev 而不是 **pprev,并且因为我们试图节省内存,所以我们不在头部包含 *prev,那么我们的 hlist 实现如下所示:

struct hlist_head {
  struct hlist_node *first = null;
};

struct hlist_node {
  struct hlist_node *next;
  struct hlist_node *prev;
};

请注意,prev 指针不能指向头部,或head->first(与**pprev 不同)。这使 hlist 实现变得复杂,正如您在我们实现 hlist_add_before() 时看到的那样:

void
hlist_init(struct hlist_head *head) {
  head->first = null;  
}

void
hlist_add_head(struct hlist_head *head, struct hlist_node *node) {
  struct hlist_node *next = head->first;

  head->first = node;
  node->next = next;
  node->prev = NULL;
  if (next) {
    next->prev = node;
  }
}

请注意,在上述hlist_add_head() 的实现中,prev 没有任何指向。所以,现在当您实现 hlist_add_before() 时,它看起来像这样:

void
hlist_add_before(struct hlist_head *head,
                 struct hlist_node *node,
                 struct hlist_next *next) {
  hlist_node *prev = next->prev;

  node->next = next;
  node->prev = prev;
  next->prev = node;

  if (prev) {
    prev->next = node;
  } else {
    head->first = node;
  }
}

请注意,现在我们还需要将 head 传递给 hlist_add_before(),这需要一个额外的 push 指令来推送 head 在堆栈上。此外,在实现中还有一个额外的条件检查,这进一步减慢了速度。

现在,尝试使用 *prev 而不是 **pprev 实现其他 hlist 操作,你会发现你的实现会比原来的要慢你在 linux 内核中看到了。

关于c - linux内核哈希表实现中双指针的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3058592/

相关文章:

linux - 在 i386 的 linux 内核 2.6.11 中,此内联汇编 (:"0"(THREAD_SIZE - 1)) 的含义是什么

c - 在汇编 x86 或 ARM 中引发软中断

linux-kernel - kprobes中未定义异常处理程序(__und_svc)的作用是什么?

c - 函数指针声明语法困惑

c - 将两个目标文件链接在一起会导致段错误 11

c++ - VC++ 替换不同对象的定义,GCC 等不

linux - Linux 中的共享 IRQ

linux - 根据重复行值拆分文本文件的内容

linux - 增加一个ip地址的并发连接数

c - 是否有等效于倒带功能的功能,但仅适用于一个 token ?