From 7f014a3fa6e9ee214d52e7c9b51aa6fb237819e5 Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Thu, 15 Mar 2018 15:57:11 -0400 Subject: [PATCH] fix all xinqiu gitbook links that contains interrupts-*.html --- Interrupts/linux-interrupts-10.md | 6 +++--- Interrupts/linux-interrupts-9.md | 8 ++++---- MM/linux-mm-3.md | 4 ++-- SyncPrim/linux-sync-6.md | 4 ++-- SysCall/linux-syscall-2.md | 2 +- Timers/linux-timers-4.md | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Interrupts/linux-interrupts-10.md b/Interrupts/linux-interrupts-10.md index 2b962d8..b629d62 100644 --- a/Interrupts/linux-interrupts-10.md +++ b/Interrupts/linux-interrupts-10.md @@ -2,7 +2,7 @@ ===================== 终结篇 ------------------------- -本文是 Linux 内核[中断和中断处理](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/index.html)的第十节。在[上一节](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/interrupts-9.html),我们了解了延后中断及其相关概念,如 `softirq`,`tasklet`,`workqueue`。本节我们继续深入这个主题,现在是见识真正的硬件驱动的时候了。 +本文是 Linux 内核[中断和中断处理](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/index.html)的第十节。在[上一节](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-9.html),我们了解了延后中断及其相关概念,如 `softirq`,`tasklet`,`workqueue`。本节我们继续深入这个主题,现在是见识真正的硬件驱动的时候了。 以 [StringARM** SA-100/21285 评估板](http://netwinder.osuosl.org/pub/netwinder/docs/intel/datashts/27813501.pdf)串行驱动为例,我们来观察驱动程序如何请求一个 [IRQ](https://en.wikipedia.org/wiki/Interrupt_request_%28PC_architecture%29) 线,一个中断被触发时会发生什么之类的。驱动程序代码位于 [drivers/tty/serial/21285.c](https://github.com/torvalds/linux/blob/master/drivers/tty/serial/21285.c) 源文件。好啦,源码在手,说走就走! @@ -297,7 +297,7 @@ if (new->thread_fn && !nested) { 准备处理中断 ------------------------------ -通过上文,我们观察了为给定的中断描述符请求中断号,为给定的中断注册 `irqaction` 结构体的过程。我们已经知道,当一个中断事件发生时,中断控制器向处理器通知该事件,处理器尝试为这个中断找到一个合适的中断门。如果你已阅读本章[第八节](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/interrupts-8.html),你应该还记得 `native_init_IRQ` 函数。这个函数会初始化本地 [APIC](https://en.wikipedia.org/wiki/Advanced_Programmable_Interrupt_Controller)。这个函数的如下部分是我们现在最感兴趣的地方: +通过上文,我们观察了为给定的中断描述符请求中断号,为给定的中断注册 `irqaction` 结构体的过程。我们已经知道,当一个中断事件发生时,中断控制器向处理器通知该事件,处理器尝试为这个中断找到一个合适的中断门。如果你已阅读本章[第八节](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-8.html),你应该还记得 `native_init_IRQ` 函数。这个函数会初始化本地 [APIC](https://en.wikipedia.org/wiki/Advanced_Programmable_Interrupt_Controller)。这个函数的如下部分是我们现在最感兴趣的地方: ```C for_each_clear_bit_from(i, used_vectors, first_system_vector) { @@ -469,7 +469,7 @@ native_irq_return_iret: * [pid](https://en.wikipedia.org/wiki/Process_identifier) * [设备树](https://en.wikipedia.org/wiki/Device_tree) * [系统调用](https://en.wikipedia.org/wiki/System_call) -* [上一节](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/interrupts-9.html) +* [上一节](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-9.html) diff --git a/Interrupts/linux-interrupts-9.md b/Interrupts/linux-interrupts-9.md index 619c189..0dba45f 100644 --- a/Interrupts/linux-interrupts-9.md +++ b/Interrupts/linux-interrupts-9.md @@ -4,7 +4,7 @@ 延后中断(软中断,Tasklets 和工作队列)介绍 -------------------------------------------------------------------------------- -这是 Linux 内核[中断和中断处理](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/index.html)的第九节,在[上一节](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/interrupts-8.html)我们分析了源文件 [arch/x86/kernel/irqinit.c](https://github.com/torvalds/linux/blob/master/arch/x86/kernel/irqinit.c) 中的 `init_IRQ` 实现。接下来的这一节我们将继续深入学习外部硬件中断的初始化。 +这是 Linux 内核[中断和中断处理](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/index.html)的第九节,在[上一节](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-8.html)我们分析了源文件 [arch/x86/kernel/irqinit.c](https://github.com/torvalds/linux/blob/master/arch/x86/kernel/irqinit.c) 中的 `init_IRQ` 实现。接下来的这一节我们将继续深入学习外部硬件中断的初始化。 中断处理会有一些特点,其中最主要的两个是: @@ -144,7 +144,7 @@ void raise_softirq(unsigned int nr) __raise_softirq_irqoff(nr); ``` -然后,通过 `in_interrupt` 函数获得 `irq_count` 值。我们在这一章的第一[小节](https://www.gitbook.com/book/xinqiu/linux-insides-cn/content/Interrupts/interrupts-1.html)已经知道它是用来检测一个 cpu 是否处于中断环境。如果我们处于中断上下文中,我们就退出 `raise_softirq_irqoff` 函数,装回 `IF` 标志位并允许当前处理器的中断。如果不在中断上下文中,就会调用 `wakeup_softirqd` 函数: +然后,通过 `in_interrupt` 函数获得 `irq_count` 值。我们在这一章的第一[小节](http://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-1.html)已经知道它是用来检测一个 cpu 是否处于中断环境。如果我们处于中断上下文中,我们就退出 `raise_softirq_irqoff` 函数,装回 `IF` 标志位并允许当前处理器的中断。如果不在中断上下文中,就会调用 `wakeup_softirqd` 函数: ```C if (!in_interrupt()) @@ -363,7 +363,7 @@ static void tasklet_action(struct softirq_action *a) } ``` -在 `tasklet_action` 开始时利用 `local_irq_disable` 宏禁用了当前处理器的中断(你可以阅读本书[第二部分](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/interrupts-2.html)了解更多关于此宏的信息)。接下来获取到当前处理器对应的普通优先级 tasklet 列表并把它设置为 `NULL` ,这是因为所有的 tasklet 都将被执行。然后使能当前处理器的中断,循环遍历 tasklet 列表,每一次遍历都会对当前 tasklet 调用 `tasklet_trylock` 函数来更新它的状态为 `TASKLET_STATE_RUN`: +在 `tasklet_action` 开始时利用 `local_irq_disable` 宏禁用了当前处理器的中断(你可以阅读本书[第二部分](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-2.html)了解更多关于此宏的信息)。接下来获取到当前处理器对应的普通优先级 tasklet 列表并把它设置为 `NULL` ,这是因为所有的 tasklet 都将被执行。然后使能当前处理器的中断,循环遍历 tasklet 列表,每一次遍历都会对当前 tasklet 调用 `tasklet_trylock` 函数来更新它的状态为 `TASKLET_STATE_RUN`: ```C static inline int tasklet_trylock(struct tasklet_struct *t) @@ -523,4 +523,4 @@ insert_work(pwq, work, worklist, work_flags); * [CPU masks](http://xinqiu.gitbooks.io/linux-insides-cn/content/Concepts/cpumask.html) * [per-cpu](http://xinqiu.gitbooks.io/linux-insides-cn/content/Concepts/per-cpu.html) * [Workqueue](https://github.com/torvalds/linux/blob/master/Documentation/workqueue.txt) -* [Previous part](http://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/interrupts-8.html) +* [Previous part](http://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-8.html) diff --git a/MM/linux-mm-3.md b/MM/linux-mm-3.md index c07caea..dc1d608 100644 --- a/MM/linux-mm-3.md +++ b/MM/linux-mm-3.md @@ -337,7 +337,7 @@ if (!pte) static struct kmemcheck_error error_fifo[CONFIG_KMEMCHECK_QUEUE_SIZE]; ``` -`kmemcheck` 声明了一个特殊的 [tasklet](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/interrupts-9.html) : +`kmemcheck` 声明了一个特殊的 [tasklet](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-9.html) : ```C static DECLARE_TASKLET(kmemcheck_tasklet, &do_wakeup, 0); @@ -428,6 +428,6 @@ Links * [translation lookaside buffer](https://en.wikipedia.org/wiki/Translation_lookaside_buffer) * [per-cpu variables](https://xinqiu.gitbooks.io/linux-insides-cn/content/Concepts/per-cpu.html) * [flags register](https://en.wikipedia.org/wiki/FLAGS_register) -* [tasklet](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/interrupts-9.html) +* [tasklet](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-9.html) * [Paging](https://xinqiu.gitbooks.io/linux-insides-cn/content/Theory/linux-theory-1.html) * [Previous part](https://xinqiu.gitbooks.io/linux-insides-cn/content/MM/linux-mm-2.html) diff --git a/SyncPrim/linux-sync-6.md b/SyncPrim/linux-sync-6.md index b4b7b40..4b30c91 100644 --- a/SyncPrim/linux-sync-6.md +++ b/SyncPrim/linux-sync-6.md @@ -303,7 +303,7 @@ static inline void raw_write_seqcount_end(seqcount_t *s) and in the end we just call the `spin_unlock` macro to give access for other readers or writers. -That's all about `sequential lock` mechanism in the Linux kernel. Of course we did not consider full [API](https://en.wikipedia.org/wiki/Application_programming_interface) of this mechanism in this part. But all other functions are based on these which we described here. For example, Linux kernel also provides some safe macros/functions to use `sequential lock` mechanism in [interrupt handlers](https://en.wikipedia.org/wiki/Interrupt_handler) of [softirq](https://0xax.gitbooks.io/linux-insides/content/Interrupts/interrupts-9.html): `write_seqclock_irq` and `write_sequnlock_irq`: +That's all about `sequential lock` mechanism in the Linux kernel. Of course we did not consider full [API](https://en.wikipedia.org/wiki/Application_programming_interface) of this mechanism in this part. But all other functions are based on these which we described here. For example, Linux kernel also provides some safe macros/functions to use `sequential lock` mechanism in [interrupt handlers](https://en.wikipedia.org/wiki/Interrupt_handler) of [softirq](https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-9.html): `write_seqclock_irq` and `write_sequnlock_irq`: ```C static inline void write_seqlock_irq(seqlock_t *sl) @@ -347,6 +347,6 @@ Links * [x86_64](https://en.wikipedia.org/wiki/X86-64) * [Timers and time management in the Linux kernel](https://0xax.gitbooks.io/linux-insides/content/Timers/) * [interrupt handlers](https://en.wikipedia.org/wiki/Interrupt_handler) -* [softirq](https://0xax.gitbooks.io/linux-insides/content/Interrupts/interrupts-9.html) +* [softirq](https://0xax.gitbooks.io/linux-insides/content/Interrupts/linux-interrupts-9.html) * [IRQ](https://en.wikipedia.org/wiki/Interrupt_request_(PC_architecture)) * [Previous part](https://0xax.gitbooks.io/linux-insides/content/SyncPrim/sync-5.html) diff --git a/SysCall/linux-syscall-2.md b/SysCall/linux-syscall-2.md index 03d9aa8..1e1ae65 100644 --- a/SysCall/linux-syscall-2.md +++ b/SysCall/linux-syscall-2.md @@ -126,7 +126,7 @@ SYSCALL 引起操作系统系统调用处理器处于特权级0,通过加载IA ``` -这就是说我们需要将系统调用入口放置到 `IA32_LSTAR` [model specific register](https://en.wikipedia.org/wiki/Model-specific_register) 。 这一操作在 Linux 内核初始过程时完成。若已阅读关于 Linux 内核中断及中断处理政界的 [第四节](http://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/interrupts-4.html) , Linux 内核调用在初始化过程中调用 `trap_init` 函数。该函数在 [arch/x86/kernel/setup.c](https://github.com/torvalds/linux/blob/master/arch/x86/kernel/setup.c) 源代码文件中定义,执行 `non-early` 异常处理(如除法错误,[协处理器](https://en.wikipedia.org/wiki/Coprocessor) 错误等 )的初始化。除了 `non-early` 异常处理的初始化外, 函数调用 [arch/x86/kernel/cpu/common.c](https://github.com/torvalds/linux/blob/master/blob/arch/x86/kernel/cpu/common.c) 中 `cpu_init` 函数,调用相同源码文件中的 `syscall_init` 完成`per-cpu` 状态初始化。 +这就是说我们需要将系统调用入口放置到 `IA32_LSTAR` [model specific register](https://en.wikipedia.org/wiki/Model-specific_register) 。 这一操作在 Linux 内核初始过程时完成。若已阅读关于 Linux 内核中断及中断处理政界的 [第四节](http://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-4.html) , Linux 内核调用在初始化过程中调用 `trap_init` 函数。该函数在 [arch/x86/kernel/setup.c](https://github.com/torvalds/linux/blob/master/arch/x86/kernel/setup.c) 源代码文件中定义,执行 `non-early` 异常处理(如除法错误,[协处理器](https://en.wikipedia.org/wiki/Coprocessor) 错误等 )的初始化。除了 `non-early` 异常处理的初始化外, 函数调用 [arch/x86/kernel/cpu/common.c](https://github.com/torvalds/linux/blob/master/blob/arch/x86/kernel/cpu/common.c) 中 `cpu_init` 函数,调用相同源码文件中的 `syscall_init` 完成`per-cpu` 状态初始化。 该函数执行系统调用入口的初始化。查看函数的实现,函数没有参数且首先填充两个特殊模块寄存器: diff --git a/Timers/linux-timers-4.md b/Timers/linux-timers-4.md index 9eee263..6209c4c 100644 --- a/Timers/linux-timers-4.md +++ b/Timers/linux-timers-4.md @@ -240,7 +240,7 @@ The last step in the `init_timers` function is the call of the: open_softirq(TIMER_SOFTIRQ, run_timer_softirq); ``` -function. The `open_softirq` function may be already familar to you if you have read the ninth [part](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/interrupts-9.html) about the interrupts and interrupt handling in the Linux kernel. In short words, the `open_softirq` function defined in the [kernel/softirq.c](https://github.com/torvalds/linux/blob/master/kernel/softirq.c) source code file and executes initialization of the deferred interrupt handler. +function. The `open_softirq` function may be already familar to you if you have read the ninth [part](https://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/linux-interrupts-9.html) about the interrupts and interrupt handling in the Linux kernel. In short words, the `open_softirq` function defined in the [kernel/softirq.c](https://github.com/torvalds/linux/blob/master/kernel/softirq.c) source code file and executes initialization of the deferred interrupt handler. In our case the deferred function is the `run_timer_softirq` function that is will be called after a hardware interrupt in the `do_IRQ` function which defined in the [arch/x86/kernel/irq.c](https://github.com/torvalds/linux/blob/master/arch/x86/kernel/irq.c) source code file. The main point of this function is to handle a software dynamic timer. The Linux kernel does not do this thing during the hardware timer interrupt handling because this is time consuming operation.