我试图了解链表和哈希表的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;
}
}
注意,现在我们还需要传递head
给hlist_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内核开发”,并且遇到了以下段落: 无需(轻松)使用浮点数 当用户空间进程使用浮点指令时,内核将管理从整数到浮点模式的转换。内核使用浮点指令时必须执行的操作因体系结构而异,但是内核通常会捕获陷阱,然后启动从整数模式到浮点模式的转换。 与用户空间不同,内核不具有对浮点的无缝支持的奢侈,因为它无法轻易地陷入陷阱。在内核内部使用浮点数需要手动