mirror of
https://github.com/MintCN/linux-insides-zh.git
synced 2026-04-25 11:11:20 +08:00
change URLs
This commit is contained in:
@@ -3,7 +3,7 @@ Linux 内核中的同步原语. 第一部分.
|
||||
|
||||
Introduction
|
||||
--------------------------------------------------------------------------------
|
||||
这一部分为 [linux-insides](http://0xax.gitbooks.io/linux-insides/content/) 这本书开启了新的章节。定时器和时间管理相关的概念在上一个[章节](https://0xax.gitbooks.io/linux-insides/content/Timers/index.html)已经描述过了。现在是时候继续了。就像你可能从这一部分的标题所了解的那样,本章节将会描述 Linux 内核中的[同步](https://en.wikipedia.org/wiki/Synchronization_%28computer_science%29)原语。
|
||||
这一部分为 [linux-insides](https://xinqiu.gitbooks.io/linux-insides-cn/content/) 这本书开启了新的章节。定时器和时间管理相关的概念在上一个[章节](https://xinqiu.gitbooks.io/linux-insides-cn/content/Timers/index.html)已经描述过了。现在是时候继续了。就像你可能从这一部分的标题所了解的那样,本章节将会描述 Linux 内核中的[同步](https://en.wikipedia.org/wiki/Synchronization_%28computer_science%29)原语。
|
||||
|
||||
像往常一样,在考虑一些同步相关的事情之前,我们会尝试去概括地了解什么是`同步原语`。事实上,同步原语是一种软件机制,提供了两个或者多个[并行](https://en.wikipedia.org/wiki/Parallel_computing)进程或者线程在不同时刻执行一段相同的代码段的能力。例如下面的代码片段:
|
||||
|
||||
@@ -20,7 +20,7 @@ clocksource_select();
|
||||
...
|
||||
mutex_unlock(&clocksource_mutex);
|
||||
```
|
||||
出自 [kernel/time/clocksource.c](https://github.com/torvalds/linux/master/kernel/time/clocksource.c) 源文件。这段代码来自于 `__clocksource_register_scale` 函数,此函数添加给定的 [clocksource](https://0xax.gitbooks.io/linux-insides/content/Timers/timers-2.html) 到时钟源列表中。这个函数在注册时钟源列表中生成两个不同的操作。例如 `clocksource_enqueue` 函数就是添加给定时钟源到注册时钟源列表——`clocksource_list` 中。注意这几行代码被两个函数所包围:`mutex_lock` 和 `mutex_unlock`,这两个函数都带有一个参数——在本例中为 `clocksource_mutex`。
|
||||
出自 [kernel/time/clocksource.c](https://github.com/torvalds/linux/master/kernel/time/clocksource.c) 源文件。这段代码来自于 `__clocksource_register_scale` 函数,此函数添加给定的 [clocksource](https://xinqiu.gitbooks.io/linux-insides-cn/content/Timers/timers-2.html) 到时钟源列表中。这个函数在注册时钟源列表中生成两个不同的操作。例如 `clocksource_enqueue` 函数就是添加给定时钟源到注册时钟源列表——`clocksource_list` 中。注意这几行代码被两个函数所包围:`mutex_lock` 和 `mutex_unlock`,这两个函数都带有一个参数——在本例中为 `clocksource_mutex`。
|
||||
|
||||
这些函数展示了基于[互斥锁 (mutex)](https://en.wikipedia.org/wiki/Mutual_exclusion) 同步原语的加锁和解锁。当 `mutex_lock` 被执行,允许我们阻止两个或两个以上线程执行这段代码,而 `mute_unlock` 还没有被互斥锁的处理拥有者锁执行。换句话说,就是阻止在 `clocksource_list`上的并行操作。为什么在这里需要使用`互斥锁`? 如果两个并行处理尝试去注册一个时钟源会怎样。正如我们已经知道的那样,其中具有最大的等级(其具有最高的频率在系统中注册的时钟源)的列表中选择一个时钟源后,`clocksource_enqueue` 函数立即将一个给定的时钟源到 `clocksource_list` 列表:
|
||||
|
||||
@@ -39,7 +39,7 @@ static void clocksource_enqueue(struct clocksource *cs)
|
||||
|
||||
如果两个并行处理尝试同时去执行这个函数,那么这两个处理可能会找到相同的 `入口 (entry)` 可能发生[竞态条件 (race condition)](https://en.wikipedia.org/wiki/Race_condition) 或者换句话说,第二个执行 `list_add` 的处理程序,将会重写第一个线程写入的时钟源。
|
||||
|
||||
除了这个简答的例子,同步原语在 Linux 内核无处不在。如果再翻阅之前的[章节] (https://0xax.gitbooks.io/linux-insides/content/Timers/index.html) 或者其他章节或者如果大概看看 Linux 内核源码,就会发现许多地方都使用同步原语。我们不考虑 `mutex` 在 Linux 内核是如何实现的。事实上,Linux 内核提供了一系列不同的同步原语:
|
||||
除了这个简答的例子,同步原语在 Linux 内核无处不在。如果再翻阅之前的[章节] (https://xinqiu.gitbooks.io/linux-insides-cn/content/Timers/index.html) 或者其他章节或者如果大概看看 Linux 内核源码,就会发现许多地方都使用同步原语。我们不考虑 `mutex` 在 Linux 内核是如何实现的。事实上,Linux 内核提供了一系列不同的同步原语:
|
||||
|
||||
* `mutex`;
|
||||
* `semaphores`;
|
||||
@@ -236,7 +236,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
|
||||
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
|
||||
}
|
||||
```
|
||||
就像你们可能了解的那样, 首先我们禁用了[抢占](https://en.wikipedia.org/wiki/Preemption_%28computing%29),通过 [include/linux/preempt.h](https://github.com/torvalds/linux/blob/master/include/linux/preempt.h) (在 Linux 内核初始化进程章节的第九[部分](https://0xax.gitbooks.io/linux-insides/content/Initialization/linux-initialization-9.html)会了解到更多关于抢占)中的 `preempt_disable` 调用实现禁用。当我们将要解开给定的`自旋锁`,抢占将会再次启用:
|
||||
就像你们可能了解的那样, 首先我们禁用了[抢占](https://en.wikipedia.org/wiki/Preemption_%28computing%29),通过 [include/linux/preempt.h](https://github.com/torvalds/linux/blob/master/include/linux/preempt.h) (在 Linux 内核初始化进程章节的第九[部分](https://xinqiu.gitbooks.io/linux-insides-cn/content/Initialization/linux-initialization-9.html)会了解到更多关于抢占)中的 `preempt_disable` 调用实现禁用。当我们将要解开给定的`自旋锁`,抢占将会再次启用:
|
||||
|
||||
```C
|
||||
static inline void __raw_spin_unlock(raw_spinlock_t *lock)
|
||||
@@ -409,7 +409,7 @@ head | 7 | - - - | 7 | tail
|
||||
|
||||
* [Concurrent computing](https://en.wikipedia.org/wiki/Concurrent_computing)
|
||||
* [Synchronization](https://en.wikipedia.org/wiki/Synchronization_%28computer_science%29)
|
||||
* [Clocksource framework](https://0xax.gitbooks.io/linux-insides/content/Timers/timers-2.html)
|
||||
* [Clocksource framework](https://xinqiu.gitbooks.io/linux-insides-cn/content/Timers/timers-2.html)
|
||||
* [Mutex](https://en.wikipedia.org/wiki/Mutual_exclusion)
|
||||
* [Race condition](https://en.wikipedia.org/wiki/Race_condition)
|
||||
* [Atomic operations](https://en.wikipedia.org/wiki/Linearizability)
|
||||
@@ -422,4 +422,4 @@ head | 7 | - - - | 7 | tail
|
||||
* [xadd instruction](http://x86.renejeschke.de/html/file_module_x86_id_327.html)
|
||||
* [NOP](https://en.wikipedia.org/wiki/NOP)
|
||||
* [Memory barriers](https://www.kernel.org/doc/Documentation/memory-barriers.txt)
|
||||
* [Previous chapter](https://0xax.gitbooks.io/linux-insides/content/Timers/index.html)
|
||||
* [Previous chapter](https://xinqiu.gitbooks.io/linux-insides-cn/content/Timers/index.html)
|
||||
|
||||
Reference in New Issue
Block a user