现在的位置: 首页 > 综合 > 正文

1.2.3 Reference Counts(引用计数)

2017年08月16日 ⁄ 综合 ⁄ 共 3789字 ⁄ 字号 评论关闭

1.2.3. Reference Counts(引用计数)

When a piece of code tries to access a data structure that has already been freed, the kernel is not very happy, and the user is rarely happy with the kernel's reaction. To avoid those nasty problems, and to make garbage collection mechanisms easier and more effective (see the section "Garbage Collection" later in this chapter), most data structures keep a reference count. Good kernel citizens increment and decrement the reference count of every data structure every time they save and release a reference, respectively, to the structure. For any data structure type that requires a reference count, the kernel component that owns the structure usually exports two functions that can be used to increment and decrement the reference count. Such functions are usually called xxx_hold and xxx_release, respectively. Sometimes the release function is called xxx_put instead (e.g., dev_put for net_device structures).

当代码试图引用一块已经被释放的数据结构,内核很不开心,调用者也不会得到满意的答复。为避免这种令人讨厌的问题出现,让垃圾回收机制更加简洁有效,绝大多说的数据结构会保持一个引用计数。好的内核公民会随着 每次数据结构引用数的增减 而增减引用计数的大小。任何需要引用计数的数据结构,其所属内核模块一般会有函数来增加和减少引用计数。这类函数常常被叫做 xxx_hold和xxx_release。释放函数有些时候也被叫做xxx_put。

While we like to assume there are no bad citizens in the kernel, developers are human, and as such they do not always write bug-free code. The use of the reference count is a simple but effective mechanism to avoid freeing still-referenced data structures. However, it does not always solve the problem completely. This is the consequence of forgetting to balance increments and decrements:
 
通常来说我们喜欢假设在内核中并没有坏公民,毕竟内核搭建者是人,他们并不是常常写出没有Bug的代码。引用计数的使用方法很简单,但是却能有效的避免释放还被引用的数据结构。然而,他并不能完全解决这个问题。因为我们有时会忘记去记录引用计数的增减:

If you release a reference to a data structure but forget to call the xxx_release function, the kernel will never allow the data structure to be freed (unless another buggy piece of code happens to call the release function an extra time by mistake!). This leads to gradual memory exhaustion.

如果你释放了一个数据连接,但是却忘了调用xxx_release函数,内核将永远不会释放该数据块(除非有另外的错误代码在另外的时间错误调用释放函数)这将会导致内存慢慢耗尽。

If you take a reference to a data structure but forget to call xxx_hold, and at some later point you happen to be the only reference holder, the structure will be prematurely freed because you are not accounted for. This case definitely can be more catastrophic than the previous one; your next attempt to access the structure can corrupt other data or cause a kernel panic that brings down the whole system instantly.
如果引用一个数据块却忘记调用xxx_hold函数,恰巧一段时间后你又成为唯一的引用者,因为引用没有被计数 ,数据块会被释放。这种情况比起前一种危害更大,你下一次读取该数据块时会污染其他数据或着引起内核混乱导致系统崩溃。

When a data structure is to be removed for some reason, the reference holders can be explicitly notified about its going away so that they can politely release their references. This is done through notification chains. See the section "Reference Counts" in Chapter 8 for an interesting example.
当一个数据块因故移除,引用持有者能够明确的提醒他的移除,以便于他们都够平和的释放那些引用。这些工作是通过提醒链来完成。

The reference count on a data structure typically can be incremented when:
一个数据结构的引用计数能被增加的情形:

There is a close relationship between two data structure types. In this case, one of the two often maintains a pointer initialized to the address of the second one.
两个个数据结构间有紧密的关联关系,在这种情况下,其中一个函数拥有某个指针,它被初始化存放另一个数据结构的地址。

A timer is started whose handler is going to access the data structure. When the timer is fired, the reference count on the structure is incremented, because the last thing you want is for the data structure to be freed before the timer expires.
一个定时器会被启动,如果他的持有者将会读取一个数据结构。当定时器开始计时,该数据结构的引用计数会增加,因为在定时器失效前你要对该数据结构作的最后动作是释放它。

A successful lookup on a list or a hash table returns a pointer to the matching element. In most cases, the returned result is used by the caller to carry out some task. Because of that, it is common for a lookup routine to increase the reference count on the matching element, and let the caller release it when necessary.
一个成功的查询链表或哈希表动作 会返回对应元素的指针,大多数时候,返回值会被调用者使用来执行一些任务。因此,让查询例程增加引用计数并在需要的时候释放计数是必要的。

When the last reference to a data structure is released, it may be freed because it is not needed anymore, but not necessarily.
当一个数据块最后的引用被释放,数据有可能被释放,因为他已经不再被需要。但这并不是必须的。

The introduction of the new sysfs filesystem has helped to make a good portion of the kernel code more aware of reference counts and consistent in its use of them.
 新文件系统的介绍里,在内核代码关于引用计数和上下文的引用里已经做了更好的讲解。(水平有限,谁能帮俺好好翻译这句!!!)

抱歉!评论已关闭.