mirror of
https://github.com/MintCN/linux-insides-zh.git
synced 2026-04-25 19:20:28 +08:00
resolve gitbook links in SysCall/Theory/DataStructure
This commit is contained in:
@@ -4,7 +4,7 @@ Linux 内核系统调用 第一节
|
||||
简介
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
这次提交为 [linux内核解密](http://xinqiu.gitbooks.io/linux-insides-cn/content/) 添加一个新的章节,从标题就可以知道, 这一章节将介绍Linux 内核中 [System Call](https://en.wikipedia.org/wiki/System_call) 的概念。章节内容的选择并非偶然。在前一[章节](http://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/index.html)我们了解了中断及中断处理。系统调用的概念与中断非常相似,这是因为软件中断是执行系统调用最常见的方式。接下来我们将从不同的角度来审视系统调用相关概念。例如,从用户空间发起系统调用时会发生什么,Linux内核中一组系统调用处理器的实现,[VDSO](https://en.wikipedia.org/wiki/VDSO) 和 [vsyscall](https://lwn.net/Articles/446528/) 的概念以及其他信息。
|
||||
这次提交为 [linux内核解密](/SUMMARY.md) 添加一个新的章节,从标题就可以知道, 这一章节将介绍Linux 内核中 [System Call](https://en.wikipedia.org/wiki/System_call) 的概念。章节内容的选择并非偶然。在前一[章节](/Interrupts/)我们了解了中断及中断处理。系统调用的概念与中断非常相似,这是因为软件中断是执行系统调用最常见的方式。接下来我们将从不同的角度来审视系统调用相关概念。例如,从用户空间发起系统调用时会发生什么,Linux内核中一组系统调用处理器的实现,[VDSO](https://en.wikipedia.org/wiki/VDSO) 和 [vsyscall](https://lwn.net/Articles/446528/) 的概念以及其他信息。
|
||||
|
||||
在了解 Linux 内核系统调用执行过程之前,让我们先来了解一些系统调用的相关原理。
|
||||
|
||||
@@ -411,4 +411,4 @@ fdput_pos(f);
|
||||
* [Virtual file system](https://en.wikipedia.org/wiki/Virtual_file_system)
|
||||
* [systemd](https://en.wikipedia.org/wiki/Systemd)
|
||||
* [epoll](https://en.wikipedia.org/wiki/Epoll)
|
||||
* [Previous chapter](http://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/index.html)
|
||||
* [Previous chapter](/Interrupts/)
|
||||
|
||||
@@ -4,7 +4,7 @@ Linux 系统内核调用 第二节
|
||||
Linux 内核如何处理系统调用
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
前一[小节](http://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-1.html) 作为本章节的第一部分描述了 Linux 内核[system call](https://en.wikipedia.org/wiki/System_call) 概念。
|
||||
前一[小节](/SysCall/linux-syscall-1.md) 作为本章节的第一部分描述了 Linux 内核[system call](https://en.wikipedia.org/wiki/System_call) 概念。
|
||||
前一节中提到通常系统调用处于内核处于操作系统层面。 前一节内容从用户空间的角度介绍,并且 [write](http://man7.org/linux/man-pages/man2/write.2.html)系统调用实现的一部分内容没有讨论。 在这一小节继续关注系统调用,在深入 Linux 内核之前,从一些理论开始。
|
||||
|
||||
程序中一个用户程序并不直接使用系统调用。 我们并未这样写 `Hello World`程序代码:
|
||||
@@ -114,7 +114,7 @@ asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
|
||||
|
||||
之后所有指向 “non-implemented” 系统调用元素的内容为 `sys_ni_syscall` 函数的地址,该函数仅返回 `-ENOSYS`。 其他元素指向 `sys_syscall_name` 函数。
|
||||
|
||||
至此,我们完成了系统调用表的填充并且 Linux 内核了解每个系统调用处理器的位置。 但是 Linux 内核在处理用户空间程序的系统调用时并未立即调用 `sys_syscall_name` 函数。 记住关于中断及中断处理的[章节](http://xinqiu.gitbooks.io/linux-insides-cn/content/Interrupts/index.html)。 当 Linux 内核获得处理中断的控制权,在调用中断处理程序前,必须做一些准备如保存用户空间寄存器、切换至新的堆栈及其他很多工作。 系统调用处理也是相同的情形。 第一件事是处理系统调用的准备,但是在 Linux 内核开始这些准备之前,系统调用的入口必须完成初始化,同时只有 Linux 内核知道如何执行这些准备。 在下一章节我们将关注 Linux 内核中关于系统调用入口的初始化过程。
|
||||
至此,我们完成了系统调用表的填充并且 Linux 内核了解每个系统调用处理器的位置。 但是 Linux 内核在处理用户空间程序的系统调用时并未立即调用 `sys_syscall_name` 函数。 记住关于中断及中断处理的[章节](/Interrupts/)。 当 Linux 内核获得处理中断的控制权,在调用中断处理程序前,必须做一些准备如保存用户空间寄存器、切换至新的堆栈及其他很多工作。 系统调用处理也是相同的情形。 第一件事是处理系统调用的准备,但是在 Linux 内核开始这些准备之前,系统调用的入口必须完成初始化,同时只有 Linux 内核知道如何执行这些准备。 在下一章节我们将关注 Linux 内核中关于系统调用入口的初始化过程。
|
||||
|
||||
系统调用入口初始化
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -125,7 +125,7 @@ asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
|
||||
SYSCALL 引起操作系统系统调用处理器处于特权级 0,其通过加载 IA32_LSTAR MSR 至 RIP 完成。
|
||||
```
|
||||
|
||||
这就是说我们需要将系统调用入口放置到 `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` 状态初始化。
|
||||
这就是说我们需要将系统调用入口放置到 `IA32_LSTAR` [model specific register](https://en.wikipedia.org/wiki/Model-specific_register)。 这一操作在 Linux 内核初始过程时完成 若你已阅读关于 Linux 内核中断及中断处理章节的[第四节](/Interrupts/linux-interrupts-4.md),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` 状态初始化。
|
||||
|
||||
该函数执行系统调用入口的初始化。 查看函数的实现,函数没有参数且首先填充两个特殊模块寄存器:
|
||||
|
||||
@@ -180,7 +180,7 @@ wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
|
||||
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
|
||||
```
|
||||
|
||||
可以从描述 Linux 内核启动过程的[章节](http://xinqiu.gitbooks.io/linux-insides-cn/content/Booting/linux-bootstrap-2.html)阅读更多关于 `Global Descriptor Table` 的内容。
|
||||
可以从描述 Linux 内核启动过程的[章节](/Booting/linux-bootstrap-2.md)阅读更多关于 `Global Descriptor Table` 的内容。
|
||||
|
||||
在 `syscall_init` 函数的尾段,通过写入 `MSR_SYSCALL_MASK` 特殊寄存器的标志位,将[标志寄存器](https://en.wikipedia.org/wiki/FLAGS_register)中的标志位屏蔽:
|
||||
|
||||
@@ -209,7 +209,7 @@ SWAPGS_UNSAFE_STACK
|
||||
#define SWAPGS_UNSAFE_STACK swapgs
|
||||
```
|
||||
|
||||
此宏将交换 GS 段选择符及 `MSR_KERNEL_GS_BASE ` 特殊模式寄存器中的值。 换句话说,将其入内核堆栈。 之后使老的堆栈指针指向 `rsp_scratch` [per-cpu](http://xinqiu.gitbooks.io/linux-insides-cn/content/Concepts/linux-cpu-1.html) 变量,并设置堆栈指针指向当前处理器的栈顶:
|
||||
此宏将交换 GS 段选择符及 `MSR_KERNEL_GS_BASE ` 特殊模式寄存器中的值。 换句话说,将其入内核堆栈。 之后使老的堆栈指针指向 `rsp_scratch` [per-cpu](/Concepts/linux-cpu-1.md) 变量,并设置堆栈指针指向当前处理器的栈顶:
|
||||
|
||||
```assembly
|
||||
movq %rsp, PER_CPU_VAR(rsp_scratch)
|
||||
@@ -373,7 +373,7 @@ USERGS_SYSRET64
|
||||
结论
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
这是 Linux 内核相关概念的第二节。 在[前一节](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-1.html)我们从用户应用程序的角度讨论了这些概念的原理。 在这一节继续深入系统调用概念的相关内容,讨论了系统调用发生时 Linux 内核执行的内容。
|
||||
这是 Linux 内核相关概念的第二节。 在[前一节](/SysCall/linux-syscall-1.md)我们从用户应用程序的角度讨论了这些概念的原理。 在这一节继续深入系统调用概念的相关内容,讨论了系统调用发生时 Linux 内核执行的内容。
|
||||
|
||||
若存在疑问及建议,在 twitter @[0xAX](https://twitter.com/0xAX),通过 [email](anotherworldofworld@gmail.com) 或者创建 [issue](https://github.com/MintCN/linux-insides-zh/issues/new)。
|
||||
|
||||
@@ -397,8 +397,8 @@ Links
|
||||
* [instruction pointer](https://en.wikipedia.org/wiki/Program_counter)
|
||||
* [flags register](https://en.wikipedia.org/wiki/FLAGS_register)
|
||||
* [Global Descriptor Table](https://en.wikipedia.org/wiki/Global_Descriptor_Table)
|
||||
* [per-cpu](http://xinqiu.gitbooks.io/linux-insides-cn/content/Concepts/linux-cpu-1.html)
|
||||
* [per-cpu](/Concepts/linux-cpu-1.md)
|
||||
* [general purpose registers](https://en.wikipedia.org/wiki/Processor_register)
|
||||
* [ABI](https://en.wikipedia.org/wiki/Application_binary_interface)
|
||||
* [x86_64 C ABI](http://www.x86-64.org/documentation/abi.pdf)
|
||||
* [previous chapter](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-1.html)
|
||||
* [previous chapter](/SysCall/linux-syscall-1.md)
|
||||
|
||||
@@ -4,7 +4,7 @@ Linux 内核系统调用 第三节
|
||||
vsyscalls 和 vDSO
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
这是讲解 Linux 内核中系统调用[章节](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/index.html)的第三部分,[前一节](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-2.html)讨论了用户空间应用程序发起的系统调用的准备工作及系统调用的处理过程。在这一节将讨论两个与系统调用十分相似的概念,这两个概念是`vsyscall` 和 `vdso`。
|
||||
这是讲解 Linux 内核中系统调用[章节](/SysCall/)的第三部分,[前一节](/SysCall/linux-syscall-2.md)讨论了用户空间应用程序发起的系统调用的准备工作及系统调用的处理过程。在这一节将讨论两个与系统调用十分相似的概念,这两个概念是`vsyscall` 和 `vdso`。
|
||||
|
||||
我们已经了解什么是`系统调用`。这是 Linux 内核一种特殊的运行机制,使得用户空间的应用程序可以请求,像写入文件和打开套接字等特权级下的任务。正如你所了解的,在 Linux 内核中发起一个系统调用是特别昂贵的操作,因为处理器需要中断当前正在执行的任务,切换内核模式的上下文,在系统调用处理完毕后跳转至用户空间。以下的两种机制 - `vsyscall` 和d `vdso` 被设计用来加速系统调用的处理,在这一节我们将了解两种机制的工作原理。
|
||||
|
||||
@@ -24,7 +24,7 @@ ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls
|
||||
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
|
||||
```
|
||||
|
||||
因此, 这些系统调用将在用户空间下执行,这意味着将不发生 [上下文切换](https://en.wikipedia.org/wiki/Context_switch)。 `vsyscall` 内存页的映射在 [arch/x86/entry/vsyscall/vsyscall_64.c](https://github.com/torvalds/linux/blob/master/arch/x86/entry/vsyscall/vsyscall_64.c) 源代码中定义的 `map_vsyscall` 函数中实现。这一函数在 Linux 内核初始化时被 [arch/x86/kernel/setup.c](https://github.com/torvalds/linux/blob/master/arch/x86/kernel/setup.c) 源代码中定义的函数`setup_arch` (我们在[第五章](http://xinqiu.gitbooks.io/linux-insides-cn/content/Initialization/linux-initialization-5.html) Linux 内核的初始化中讨论过该函数)。
|
||||
因此, 这些系统调用将在用户空间下执行,这意味着将不发生 [上下文切换](https://en.wikipedia.org/wiki/Context_switch)。 `vsyscall` 内存页的映射在 [arch/x86/entry/vsyscall/vsyscall_64.c](https://github.com/torvalds/linux/blob/master/arch/x86/entry/vsyscall/vsyscall_64.c) 源代码中定义的 `map_vsyscall` 函数中实现。这一函数在 Linux 内核初始化时被 [arch/x86/kernel/setup.c](https://github.com/torvalds/linux/blob/master/arch/x86/kernel/setup.c) 源代码中定义的函数`setup_arch` (我们在[第五章](/Initialization/linux-initialization-5.md) Linux 内核的初始化中讨论过该函数)。
|
||||
|
||||
注意 `map_vsyscall` 函数的实现依赖于内核配置选项 `CONFIG_X86_VSYSCALL_EMULATION` :
|
||||
|
||||
@@ -49,7 +49,7 @@ void __init map_vsyscall(void)
|
||||
}
|
||||
```
|
||||
|
||||
在 `map_vsyscall` 函数的开始,通过宏 `__pa_symbol` 获取了 `vsyscall` 内存页的物理地址(我们已在[第四章](http://xinqiu.gitbooks.io/linux-insides-cn/content/Initialization/linux-initialization-4.html) of the Linux kernel initialization process)讨论了该宏的实现)。`__vsyscall_page` 在 [arch/x86/entry/vsyscall/vsyscall_emu_64.S](https://github.com/torvalds/linux/blob/master/arch/x86/entry/vsyscall/vsyscall_emu_64.S) 汇编源代码文件中定义, 具有如下的 [虚拟地址](https://en.wikipedia.org/wiki/Virtual_address_space):
|
||||
在 `map_vsyscall` 函数的开始,通过宏 `__pa_symbol` 获取了 `vsyscall` 内存页的物理地址(我们已在[第四章](/Initialization/linux-initialization-4.md) of the Linux kernel initialization process)讨论了该宏的实现)。`__vsyscall_page` 在 [arch/x86/entry/vsyscall/vsyscall_emu_64.S](https://github.com/torvalds/linux/blob/master/arch/x86/entry/vsyscall/vsyscall_emu_64.S) 汇编源代码文件中定义, 具有如下的 [虚拟地址](https://en.wikipedia.org/wiki/Virtual_address_space):
|
||||
|
||||
```
|
||||
ffffffff81881000 D __vsyscall_page
|
||||
@@ -80,7 +80,7 @@ __vsyscall_page:
|
||||
ret
|
||||
```
|
||||
|
||||
回到 `map_vsyscall` 函数及 `__vsyscall_page` 的实现,在得到 `__vsyscall_page` 的物理地址之后,使用 `__set_fixmap` 为 `vsyscall` 内存页 检查设置 [fix-mapped](http://xinqiu.gitbooks.io/linux-insides-cn/content/MM/linux-mm-2.html)地址的变量`vsyscall_mode`:
|
||||
回到 `map_vsyscall` 函数及 `__vsyscall_page` 的实现,在得到 `__vsyscall_page` 的物理地址之后,使用 `__set_fixmap` 为 `vsyscall` 内存页 检查设置 [fix-mapped](/MM/linux-mm-2.md)地址的变量`vsyscall_mode`:
|
||||
|
||||
```C
|
||||
if (vsyscall_mode != NONE)
|
||||
@@ -140,9 +140,9 @@ static int __init vsyscall_setup(char *str)
|
||||
early_param("vsyscall", vsyscall_setup);
|
||||
```
|
||||
|
||||
关于 `early_param` 宏的更多信息可以在[第六章](http://xinqiu.gitbooks.io/linux-insides-cn/content/Initialization/linux-initialization-6.html) Linux 内核初始化中找到。
|
||||
关于 `early_param` 宏的更多信息可以在[第六章](/Initialization/linux-initialization-6.md) Linux 内核初始化中找到。
|
||||
|
||||
在函数 `vsyscall_map` 的最后仅通过 [BUILD_BUG_ON](http://xinqiu.gitbooks.io/linux-insides-cn/content/Initialization/linux-initialization-1.html) 宏检查 `vsyscall` 内存页的虚拟地址是否等于变量 `VSYSCALL_ADDR` :
|
||||
在函数 `vsyscall_map` 的最后仅通过 [BUILD_BUG_ON](/Initialization/linux-initialization-1.md) 宏检查 `vsyscall` 内存页的虚拟地址是否等于变量 `VSYSCALL_ADDR` :
|
||||
|
||||
```C
|
||||
BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_PAGE) !=
|
||||
@@ -252,7 +252,7 @@ Here we can see that [uname](https://en.wikipedia.org/wiki/Uname) util was linke
|
||||
* `libc.so.6`;
|
||||
* `ld-linux-x86-64.so.2`.
|
||||
|
||||
The first provides `vDSO` functionality, the second is `C` [standard library](https://en.wikipedia.org/wiki/C_standard_library) and the third is the program interpreter (more about this you can read in the part that describes [linkers](https://xinqiu.gitbooks.io/linux-insides-cn/content/Misc/linux-misc-3.html)). So, the `vDSO` solves limitations of the `vsyscall`. Implementation of the `vDSO` is similar to `vsyscall`.
|
||||
The first provides `vDSO` functionality, the second is `C` [standard library](https://en.wikipedia.org/wiki/C_standard_library) and the third is the program interpreter (more about this you can read in the part that describes [linkers](/Misc/linux-misc-3.md)). So, the `vDSO` solves limitations of the `vsyscall`. Implementation of the `vDSO` is similar to `vsyscall`.
|
||||
|
||||
Initialization of the `vDSO` occurs in the `init_vdso` function that defined in the [arch/x86/entry/vdso/vma.c](https://github.com/torvalds/linux/blob/master/arch/x86/entry/vdso/vma.c) source code file. This function starts from the initialization of the `vDSO` images for 32-bits and 64-bits depends on the `CONFIG_X86_X32_ABI` kernel configuration option:
|
||||
|
||||
@@ -370,11 +370,11 @@ That's all.
|
||||
Conclusion
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
This is the end of the third part about the system calls concept in the Linux kernel. In the previous [part](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-2.html) we discussed the implementation of the preparation from the Linux kernel side, before a system call will be handled and implementation of the `exit` process from a system call handler. In this part we continued to dive into the stuff which is related to the system call concept and learned two new concepts that are very similar to the system call - the `vsyscall` and the `vDSO`.
|
||||
This is the end of the third part about the system calls concept in the Linux kernel. In the previous [part](/SysCall/linux-syscall-2.md) we discussed the implementation of the preparation from the Linux kernel side, before a system call will be handled and implementation of the `exit` process from a system call handler. In this part we continued to dive into the stuff which is related to the system call concept and learned two new concepts that are very similar to the system call - the `vsyscall` and the `vDSO`.
|
||||
|
||||
After all of these three parts, we know almost all things that are related to system calls, we know what system call is and why user applications need them. We also know what occurs when a user application calls a system call and how the kernel handles system calls.
|
||||
|
||||
The next part will be the last part in this [chapter](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/index.html) and we will see what occurs when a user runs the program.
|
||||
The next part will be the last part in this [chapter](/SysCall/) and we will see what occurs when a user runs the program.
|
||||
|
||||
If you have questions or suggestions, feel free to ping me in twitter [0xAX](https://twitter.com/0xAX), drop me [email](anotherworldofworld@gmail.com) or just create [issue](https://github.com/MintCN/linux-insides-zh/issues/new).
|
||||
|
||||
@@ -390,14 +390,14 @@ Links
|
||||
* [virtual address](https://en.wikipedia.org/wiki/Virtual_address_space)
|
||||
* [Segmentation](https://en.wikipedia.org/wiki/Memory_segmentation)
|
||||
* [enum](https://en.wikipedia.org/wiki/Enumerated_type)
|
||||
* [fix-mapped addresses](http://xinqiu.gitbooks.io/linux-insides-cn/content/MM/linux-mm-2.html)
|
||||
* [fix-mapped addresses](MM/linux-mm-2.md)
|
||||
* [glibc](https://en.wikipedia.org/wiki/GNU_C_Library)
|
||||
* [BUILD_BUG_ON](http://xinqiu.gitbooks.io/linux-insides-cn/content/Initialization/linux-initialization-1.html)
|
||||
* [BUILD_BUG_ON](/Initialization/linux-initialization-1.md)
|
||||
* [Processor register](https://en.wikipedia.org/wiki/Processor_register)
|
||||
* [Page fault](https://en.wikipedia.org/wiki/Page_fault)
|
||||
* [segementation fault](https://en.wikipedia.org/wiki/Segmentation_fault)
|
||||
* [instruction pointer](https://en.wikipedia.org/wiki/Program_counter)
|
||||
* [stack pointer](https://en.wikipedia.org/wiki/Stack_register)
|
||||
* [uname](https://en.wikipedia.org/wiki/Uname)
|
||||
* [Linkers](https://xinqiu.gitbooks.io/linux-insides-cn/content/Misc/linux-misc-3.html)
|
||||
* [Previous part](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-2.html)
|
||||
* [Linkers](/Misc/linux-misc-3.md)
|
||||
* [Previous part](/SysCall/linux-syscall-2.md)
|
||||
|
||||
@@ -4,7 +4,7 @@ System calls in the Linux kernel. Part 4.
|
||||
How does the Linux kernel run a program
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
This is the fourth part of the [chapter](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/index.html) that describes [system calls](https://en.wikipedia.org/wiki/System_call) in the Linux kernel and as I wrote in the conclusion of the [previous](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-3.html) - this part will be last in this chapter. In the previous part we stopped at the two new concepts:
|
||||
This is the fourth part of the [chapter](/SysCall/) that describes [system calls](https://en.wikipedia.org/wiki/System_call) in the Linux kernel and as I wrote in the conclusion of the [previous](/SysCall/linux-syscall-3.md) - this part will be last in this chapter. In the previous part we stopped at the two new concepts:
|
||||
|
||||
* `vsyscall`;
|
||||
* `vDSO`;
|
||||
@@ -73,7 +73,7 @@ So, an user application (`bash` in our case) calls the system call and as we alr
|
||||
execve system call
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
We saw preparation before a system call called by an user application and after a system call handler finished its work in the second [part](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-2.html) of this chapter. We stopped at the call of the `execve` system call in the previous paragraph. This system call defined in the [fs/exec.c](https://github.com/torvalds/linux/blob/master/fs/exec.c) source code file and as we already know it takes three arguments:
|
||||
We saw preparation before a system call called by an user application and after a system call handler finished its work in the second [part](/SysCall/linux-syscall-2.md) of this chapter. We stopped at the call of the `execve` system call in the previous paragraph. This system call defined in the [fs/exec.c](https://github.com/torvalds/linux/blob/master/fs/exec.c) source code file and as we already know it takes three arguments:
|
||||
|
||||
```
|
||||
SYSCALL_DEFINE3(execve,
|
||||
@@ -334,7 +334,7 @@ if (!elf_phdata)
|
||||
goto out;
|
||||
```
|
||||
|
||||
that describes [segments](https://en.wikipedia.org/wiki/Memory_segmentation). Read the `program interpreter` and libraries that linked with the our executable binary file from disk and load it to memory. The `program interpreter` specified in the `.interp` section of the executable file and as you can read in the part that describes [Linkers](https://xinqiu.gitbooks.io/linux-insides-cn/content/Misc/linux-misc-3.html) it is - `/lib64/ld-linux-x86-64.so.2` for the `x86_64`. It setups the stack and map `elf` binary into the correct location in memory. It maps the [bss](https://en.wikipedia.org/wiki/.bss) and the [brk](http://man7.org/linux/man-pages/man2/sbrk.2.html) sections and does many many other different things to prepare executable file to execute.
|
||||
that describes [segments](https://en.wikipedia.org/wiki/Memory_segmentation). Read the `program interpreter` and libraries that linked with the our executable binary file from disk and load it to memory. The `program interpreter` specified in the `.interp` section of the executable file and as you can read in the part that describes [Linkers](/Misc/linux-misc-3.md) it is - `/lib64/ld-linux-x86-64.so.2` for the `x86_64`. It setups the stack and map `elf` binary into the correct location in memory. It maps the [bss](https://en.wikipedia.org/wiki/.bss) and the [brk](http://man7.org/linux/man-pages/man2/sbrk.2.html) sections and does many many other different things to prepare executable file to execute.
|
||||
|
||||
In the end of the execution of the `load_elf_binary` we call the `start_thread` function and pass three arguments to it:
|
||||
|
||||
@@ -424,7 +424,7 @@ Links
|
||||
* [Alpha](https://en.wikipedia.org/wiki/DEC_Alpha)
|
||||
* [FDPIC](http://elinux.org/UClinux_Shared_Library#FDPIC_ELF)
|
||||
* [segments](https://en.wikipedia.org/wiki/Memory_segmentation)
|
||||
* [Linkers](https://xinqiu.gitbooks.io/linux-insides-cn/content/Misc/linux-misc-3.html)
|
||||
* [Linkers](/Misc/linux-misc-3.md)
|
||||
* [Processor register](https://en.wikipedia.org/wiki/Processor_register)
|
||||
* [instruction pointer](https://en.wikipedia.org/wiki/Program_counter)
|
||||
* [Previous part](http://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-3.html)
|
||||
* [Previous part](/SysCall/linux-syscall-3.md)
|
||||
|
||||
@@ -59,7 +59,7 @@ SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
|
||||
}
|
||||
```
|
||||
|
||||
如果你阅读过[上一节](https://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-4.html),你应该知道系统调用通过 `SYSCALL_DEFINE` 宏定义实现。因此,`open` 系统调用也不例外。
|
||||
如果你阅读过[上一节](/SysCall/linux-syscall-4.md),你应该知道系统调用通过 `SYSCALL_DEFINE` 宏定义实现。因此,`open` 系统调用也不例外。
|
||||
|
||||
`open` 系统调用位于 [fs/open.c](https://github.com/torvalds/linux/blob/16f73eb02d7e1765ccab3d2018e0bd98eb93d973/fs/open.c) 源文件中,粗看非常简短
|
||||
|
||||
@@ -406,4 +406,4 @@ Linux 内核中关于不同系统调用的实现的第五部分已经完成了
|
||||
* [inode](https://en.wikipedia.org/wiki/Inode)
|
||||
* [RCU](https://www.kernel.org/doc/Documentation/RCU/whatisRCU.txt)
|
||||
* [read](http://man7.org/linux/man-pages/man2/read.2.html)
|
||||
* [previous part](https://0xax.gitbooks.io/linux-insides/content/SysCall/syscall-4.html)
|
||||
* [previous part](/SysCall/linux-syscall-4.md)
|
||||
Reference in New Issue
Block a user