From f5cc72767e066a162e7a7f084d6d7d31c65261bb Mon Sep 17 00:00:00 2001 From: Dongliang Mu Date: Fri, 3 May 2024 17:04:08 +0800 Subject: [PATCH] resolve gitbook links in Misc --- Misc/linux-misc-1.md | 4 ++-- Misc/linux-misc-3.md | 6 +++--- Misc/linux-misc-4.md | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Misc/linux-misc-1.md b/Misc/linux-misc-1.md index 57e37d9..d745195 100644 --- a/Misc/linux-misc-1.md +++ b/Misc/linux-misc-1.md @@ -4,11 +4,11 @@ Linux 内核开发 简介 -------------------------------------------------------------------------------- -如你所知,我从去年开始写了一系列关于 `x86_64` 架构汇编语言程序设计的[博文](http://xinqiu.gitbooks.io/categories/assembly/)。除了大学期间写过一些 `Hello World` 这样无实用价值的程序之外,我从来没写过哪怕一行的底层代码。那些程序也是很久以前的事情了,就像我刚才说的,我几乎完全没有写过底层代码。直到不久前,我才开始对这些事情感兴趣,因为我意识到我虽然可以写出程序,但是我却不知道我的程序是怎样被组织运行的。 +如你所知,我从去年开始写了一系列关于 `x86_64` 架构汇编语言程序设计的[博文](https://0xax.github.io/categories/assembler/)。除了大学期间写过一些 `Hello World` 这样无实用价值的程序之外,我从来没写过哪怕一行的底层代码。那些程序也是很久以前的事情了,就像我刚才说的,我几乎完全没有写过底层代码。直到不久前,我才开始对这些事情感兴趣,因为我意识到我虽然可以写出程序,但是我却不知道我的程序是怎样被组织运行的。 在写了一些汇编代码之后,我开始**大致**了解了程序在编译之后会变成什么样子。尽管如此,还是有很多其他的东西我不能够理解。例如:当 `syscall` 指令在我的汇编程序内执行时究竟发生了什么,当 `printf` 函数开始工作时又发生了什么,还有,我的程序是如何通过网络与其他计算机进行通信的。[汇编](https://en.wikipedia.org/wiki/Assembly_language#Assembler)语言并没有为这些问题带来答案,于是我决定做一番深入研究。我开始学习 Linux 内核的源代码,并且尝试着理解那些让我感兴趣的东西。然而 Linux 内核源代码也没有解答我**所有的**问题,不过我自身关于 Linux 内核及其外围流程的知识确实掌握的更好了。 -在我开始学习 Linux 内核的九个半月之后,我写了这部分内容,并且发布了本书的[第一部分](https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-1.html)。到现在为止,本书共包括了四个部分,而这并不是终点。我之所以写这一系列关于 Linux 内核的文章其实更多的是为了我自己。你也知道,Linux 内核的代码量极其巨大,另外还非常容易忘记这一块或那一块内核代码做了什么,或者忘记某些东西是怎么实现的。出乎意料的是 [linux-insides](https://github.com/0xAX/linux-insides) 很快就火了,并且在九个月后积攒了 `9096` 个星星: +在我开始学习 Linux 内核的九个半月之后,我写了这部分内容,并且发布了本书的[第一部分](/Booting/linux-bootstrap-1.md)。到现在为止,本书共包括了四个部分,而这并不是终点。我之所以写这一系列关于 Linux 内核的文章其实更多的是为了我自己。你也知道,Linux 内核的代码量极其巨大,另外还非常容易忘记这一块或那一块内核代码做了什么,或者忘记某些东西是怎么实现的。出乎意料的是 [linux-insides](https://github.com/0xAX/linux-insides) 很快就火了,并且在九个月后积攒了 `9096` 个星星: ![github](http://s2.postimg.org/jjb3s4frt/stars.png) diff --git a/Misc/linux-misc-3.md b/Misc/linux-misc-3.md index 294b735..460cea4 100644 --- a/Misc/linux-misc-3.md +++ b/Misc/linux-misc-3.md @@ -1,7 +1,7 @@ 介绍 --------------- -在写 [linux-insides](http://0xax.gitbooks.io/linux-insides/content/) 一书的过程中,我收到了很多邮件询问关于[链接器](https://zh.wikipedia.org/wiki/%E9%93%BE%E6%8E%A5%E5%99%A8)和链接器脚本的问题。所以我决定写这篇文章来介绍链接器和目标文件的链接方面的知识。 +在写 [linux-insides](/SUMMARY.md) 一书的过程中,我收到了很多邮件询问关于[链接器](https://zh.wikipedia.org/wiki/%E9%93%BE%E6%8E%A5%E5%99%A8)和链接器脚本的问题。所以我决定写这篇文章来介绍链接器和目标文件的链接方面的知识。 如果我们打开维基百科的 `链接器` 页,我们将会看到如下定义: @@ -567,7 +567,7 @@ Disassembly of section .data: ... ``` -除了我们已经看到的命令,另外还有一些。首先是 `ASSERT(exp, message)` ,保证给定的表达式不为零。如果为零,那么链接器会退出同时返回错误码,打印错误信息。如果你已经阅读了 [linux-insides](https://xinqiu.gitbooks.io/linux-insides-cn/content/) 的 Linux 内核启动流程,你或许知道 Linux 内核的设置头的偏移为 `0x1f1`。在 Linux 内核的链接器脚本中,我们可以看到下面的校验: +除了我们已经看到的命令,另外还有一些。首先是 `ASSERT(exp, message)` ,保证给定的表达式不为零。如果为零,那么链接器会退出同时返回错误码,打印错误信息。如果你已经阅读了 [linux-insides](/Booting/README.md) 的 Linux 内核启动流程,你或许知道 Linux 内核的设置头的偏移为 `0x1f1`。在 Linux 内核的链接器脚本中,我们可以看到下面的校验: ``` . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); @@ -627,7 +627,7 @@ SECTIONS 相关链接 ----------------- -* [Book about Linux kernel insides](http://0xax.gitbooks.io/linux-insides/content/) +* [Book about Linux kernel insides](/SUMMARY.md) * [linker](https://en.wikipedia.org/wiki/Linker_%28computing%29) * [object files](https://en.wikipedia.org/wiki/Object_file) * [glibc](https://en.wikipedia.org/wiki/GNU_C_Library) diff --git a/Misc/linux-misc-4.md b/Misc/linux-misc-4.md index 2f56b8c..7e8bd9a 100644 --- a/Misc/linux-misc-4.md +++ b/Misc/linux-misc-4.md @@ -4,9 +4,9 @@ 简介 -------------------------------------------------------------------------------- -虽然 [linux-insides-zh](https://www.gitbook.com/book/xinqiu/linux-insides-cn/details) 大多描述的是内核相关的东西,但是我已经决定写一个大多与用户空间相关的部分。 +虽然 linux-insides-zh 大多描述的是内核相关的东西,但是我已经决定写一个大多与用户空间相关的部分。 -[系统调用](https://zh.wikipedia.org/wiki/%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8)章节的[第四部分](https://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-4.html)已经描述了当我们想运行一个程序, Linux 内核的行为。这部分我想研究一下从用户空间的角度,当我们在 Linux 系统上运行一个程序,会发生什么。 +[系统调用](https://zh.wikipedia.org/wiki/%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8)章节的[第四部分](/SysCall/linux-syscall-4.md)已经描述了当我们想运行一个程序, Linux 内核的行为。这部分我想研究一下从用户空间的角度,当我们在 Linux 系统上运行一个程序,会发生什么。 我不知道你知识储备如何,但是在我的大学时期我学到,一个 `C` 程序从一个叫做 main 的函数开始执行。而且,这是部分正确的。每时每刻,当我们开始写一个新的程序时,我们从下面的实例代码开始编程: @@ -123,7 +123,7 @@ x + y + z = 6 > The exec() family of functions replaces the current process image with a new process image. -如果你已经阅读过[系统调用](https://zh.wikipedia.org/wiki/%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8)章节的[第四部分](https://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-4.html),你可能就知道 execve 这个系统调用定义在 [files/exec.c](https://github.com/torvalds/linux/blob/master/fs/exec.c#L1859) 文件中,并且如下所示, +如果你已经阅读过[系统调用](https://zh.wikipedia.org/wiki/%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8)章节的[第四部分](/SysCall/linux-syscall-4.md),你可能就知道 execve 这个系统调用定义在 [files/exec.c](https://github.com/torvalds/linux/blob/master/fs/exec.c#L1859) 文件中,并且如下所示, ```C SYSCALL_DEFINE3(execve, @@ -135,7 +135,7 @@ SYSCALL_DEFINE3(execve, } ``` -它以可执行文件的名字,命令行参数的集合以及环境变量的集合作为参数。正如你猜测的,每一件事都是 `do_execve` 函数完成的。在这里我将不描述这个函数的实现细节,因为你可以从[这里](https://xinqiu.gitbooks.io/linux-insides-cn/content/SysCall/linux-syscall-4.html)读到。但是,简而言之,`do_execve` 函数会检查诸如文件名是否有效,未超出进程数目限制等等。在这些检查之后,这个函数会解析 [ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 格式的可执行文件,为新的可执行文件创建内存描述符,并且在栈,堆等内存区域填上适当的值。当二进制镜像设置完成,`start_thread` 函数会设置一个新的进程。这个函数是框架相关的,而且对于 [x86_64](https://en.wikipedia.org/wiki/X86-64) 框架,它的定义是在 [arch/x86/kernel/process_64.c](https://github.com/torvalds/linux/blob/master/arch/x86/kernel/process_64.c#L231) 文件中。 +它以可执行文件的名字,命令行参数的集合以及环境变量的集合作为参数。正如你猜测的,每一件事都是 `do_execve` 函数完成的。在这里我将不描述这个函数的实现细节,因为你可以从[这里](/SysCall/linux-syscall-4.md)读到。但是,简而言之,`do_execve` 函数会检查诸如文件名是否有效,未超出进程数目限制等等。在这些检查之后,这个函数会解析 [ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 格式的可执行文件,为新的可执行文件创建内存描述符,并且在栈,堆等内存区域填上适当的值。当二进制镜像设置完成,`start_thread` 函数会设置一个新的进程。这个函数是框架相关的,而且对于 [x86_64](https://en.wikipedia.org/wiki/X86-64) 框架,它的定义是在 [arch/x86/kernel/process_64.c](https://github.com/torvalds/linux/blob/master/arch/x86/kernel/process_64.c#L231) 文件中。 `start_thread` 为[段寄存器](https://en.wikipedia.org/wiki/X86_memory_segmentation)设置新的值。从这一点开始,新进程已经准备就绪。一旦[进程切换]((https://en.wikipedia.org/wiki/Context_switch))完成,控制权就会返回到用户空间,并且新的可执行文件将会执行。