当前位置: 首页 > 面试题库 >

在Linux内核哈希列表实现中使用双指针

苍烨然
2023-03-14
问题内容

我试图了解链表和哈希表的Linux内核实现。实现的链接在这里。我了解链表的实现。但是我对为什么在hlist(*
pprev)中使用双指针感到困惑。hlist的链接在这里。我知道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;
  }
}

请注意prev,在上述的实现中,没有什么可指的hlist_add_head()。因此,现在实现时,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;
  }
}

注意,现在我们还需要传递headhlist_add_before(),这需要额外的push指令来压head入堆栈。此外,在实现中还有一个额外的条件检查,这会进一步降低速度。

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



 类似资料:
  • 我正在尝试使用javascript实现哈希表。目前,一切都正常,但我的get方法在给定特定键的哈希表中检索值时遇到了麻烦。我使用线性探测来避免冲突。当我散列键“亚历杭德罗”时,我将键映射到0索引。然后我将其添加到我的哈希表中。然后我尝试“Rosalby”,它也映射到0索引。我使用线性探测来找到下一个可用的插槽,在我的例子中,空索引是1,我将Rosalby的值放在那个插槽中。到目前为止,我似乎很好地

  • 问题内容: 在多处理器上,每个内核可以有自己的变量。我以为它们是在不同地址中的不同变量,尽管它们在同一过程中并且具有相同的名称。 但是我想知道,内核如何实现呢?它是否分配了一块内存来存放所有的percpu指针,并且每次它通过shift或其他方式将指针重定向到某个地址时? 问题答案: 普通全局变量不是每个CPU的。自动变量位于堆栈中,并且不同的CPU使用不同的堆栈,因此自然会得到单独的变量。 我猜您

  • 问题内容: 在Java中,如果我创建一个并将N个元素放入其中,它将占用多少内存?如果依赖于实现,那么什么才是好的“猜测”? 问题答案: 编辑; 噢,天哪,我是个白痴,我提供了HashMap的信息,而不是HashTable的信息。 但是,检查后,出于内存目的,实现是相同的。 这取决于您的VM的内部内存设置(项目的包装,32位或64位指针以及字对齐/大小),并且不是由Java指定的。 可以在这里找到有

  • 请帮助选择如何存储消息: 1) 2) SET似乎比LIST更容易使用,但Redis会在每条消息中存储字段名,从而使内存使用量增加一倍吗?

  • 问题内容: 所有, 下面的代码来自“ Unix环境中的高级编程”,它创建一个新线程,并打印主线程和新线程的进程ID和线程ID。 在书中,它表示在linux中,此代码的输出将显示两个线程具有不同的进程ID,因为pthread使用轻量级进程来模拟线程。但是,当我在Ubuntu 12.04中运行此代码时,它具有内核3.2,并打印了相同的pid。 那么,新的Linux内核是否会更改pthread的内部实现

  • 问题内容: 我正在阅读Robert Love的“ Linux内核开发”,并且遇到了以下段落: 无需(轻松)使用浮点数 当用户空间进程使用浮点指令时,内核将管理从整数到浮点模式的转换。内核使用浮点指令时必须执行的操作因体系结构而异,但是内核通常会捕获陷阱,然后启动从整数模式到浮点模式的转换。 与用户空间不同,内核不具有对浮点​​的无缝支持的奢侈,因为它无法轻易地陷入陷阱。在内核内部使用浮点数需要手动