将 HarmonyOS | 鸿蒙 研究到底 < 国内 | 国外 >
百篇博客系列篇.本篇为:
本篇是以下篇的延续,建议先看
v54.xx 鸿蒙内核源码分析(静态链接篇) | 完整小项目看透静态链接过程 | 51 .c .h .o
v53.xx 鸿蒙内核源码分析(ELF解析篇) | 你要忘了她姐俩你就不是银 | 51 .c .h .o
v51.xx 鸿蒙内核源码分析(ELF格式篇) | 应用程序入口并不是main | 51 .c .h .o
v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙看这篇或许真的够了 | 51 .c .h .o
一个程序从源码到被执行,当中经历了3个过程:
重定位就是把程序的逻辑地址空间变换成内存中的实际物理地址空间的过程。它是实现多道程序在内存中同时运行的基础。重定位有两种,分别是动态重定位与静态重定位。
类型 | 公式 | 具体描述 |
---|---|---|
R_X86_64_32 | 公式:S+A S:重定项中VALUE成员所指符号的内存地址 A:被重定位处原值,表示"引用符号的内存地址"与S的偏移 |
全局变量,在不加-fPIC编译生成的.o文件中,每个引用处对应一个R_X86_64_32重定位项,非static全局变量,在不加-fPIC编译生成的.so文件中,每个引用处对应一个R_X86_64_32重定位项. |
R_X86_64_PC32 | 公式:S+A-P S:重定项中VALUE成员所指符号的内存地址 A:被重定位处原值,表示"被重定位处"与"下一条指令"的偏移 P:被重定位处的内存地址 |
非static函数,在不加-fPIC编译生成的.o和.so文件中,每个调用处对应一个R_X86_64_PC32重定位项 |
R_X86_64_PLT32 | 公式:L+A-P L:<重定项中VALUE成员所指符号@plt>的内存地址 A:被重定位处原值,表示"被重定位处"相对于"下一条指令"的偏移 P:被重定位处的内存地址 |
非static函数,在加-fPIC编译生成的.o文件中,每个调用处对应一个R_386_PLT32重定位项. |
R_X86_64_RELATIVE | 公式:B+A B:.so文件加载到内存中的基地址 A:被重定位处原值,表示引用符号在.so文件中的偏移 |
static全局变量,在不加-fPIC编译生成的.so文件中,每个引用处对应一个R_X86_64_RELATIVE重定位项. |
R_X86_64_GOT32 | 公式:G G:引用符号的地址指针,相对于GOT的偏移 |
非static全局变量,在加-fPIC编译生成的.o文件中,每个引用处对应一个R_X86_64_GOT32重定位项 |
R_X86_64_GOTOFF | 公式:S-GOT S:重定项中VALUE成员所指符号的内存地址 GOT:运行时,.got段的结束地址 |
static全局变量,在加-fPIC编译生成的.o文件中,每个引用处对应一个R_X86_64_GOTOFF重定位项. |
R_X86_64_GOLB_DAT | 公式:S S:重定项中VALUE成员所指符号的内存地址 |
非static全局变量,在加-fPIC编译生成的.so文件中,每个引用处对应一个R_X86_64_GOLB_DAT重定位项. |
R_X86_64_COPY | 公式:无 | .out中利用extern引用.so中的变量,每个引用处对应一个R_X86_64_COPY重定位项. |
R_X86_64_JUMP_SLOT | 公式:S(与R_386_GLOB_DAT的公式一样,但对于动态ld,R_386_JMP_SLOT类型与R_386_RELATIVE等价) S:重定项中VALUE成员所指符号的内存地址 |
非static函数,在加-fPIC编译生成的.so文件中,每个调用处对应一个R_X86_64_JMP_SLOT重定位项. |
R_X86_64_GOTPC | 公式:GOT+A-P GOT:运行时,.got段的结束地址 A:被重定位处原值,表示"被重定位处"在机器码中的偏移 P:被重定位处的内存地址 |
全局变量,在加-fPIC编译生成的.o文件中,会额外生成R_X86_64_PC32和R_X86_64_GOTPC重定位项,非static函数,在加-fPIC编译生成的.o文件中,也会额外 生成R_X86_64_PC32和R_X86_64_GOTPC重定位项. |
解读
objdump命令是Linux下的反汇编目标文件或者可执行文件的命令,它以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息.本篇将用它说明静态重定位的实现细节和动态重定位前置条件准备.先整体走读下objdump
命令
root@5e3abe332c5a:/home/docker/test4harmony/54# objdump
Usage: objdump
root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -S ./obj/main.o
./obj/main.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 :
#include
#include "part.h"
extern int g_int;
extern char *g_str;
int main() {
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: 48 83 ec 10 sub $0x10,%rsp
int loc_int = 53;
c: c7 45 f4 35 00 00 00 movl $0x35,-0xc(%rbp)
char *loc_str = "harmony os";
13: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # 1a
1a: 48 89 45 f8 mov %rax,-0x8(%rbp)
printf("main 开始 - 全局 g_int = %d, 全局 g_str = %s.\n", g_int, g_str);
1e: 48 8b 15 00 00 00 00 mov 0x0(%rip),%rdx # 25
25: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 2b
2b: 89 c6 mov %eax,%esi
2d: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 34
34: b8 00 00 00 00 mov $0x0,%eax
39: e8 00 00 00 00 callq 3e
func_int(loc_int);
3e: 8b 45 f4 mov -0xc(%rbp),%eax
41: 89 c7 mov %eax,%edi
43: e8 00 00 00 00 callq 48
func_str(loc_str);
48: 48 8b 45 f8 mov -0x8(%rbp),%rax
4c: 48 89 c7 mov %rax,%rdi
4f: e8 00 00 00 00 callq 54
printf("main 结束 - 全局 g_int = %d, 全局 g_str = %s.\n", g_int, g_str);
54: 48 8b 15 00 00 00 00 mov 0x0(%rip),%rdx # 5b
5b: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 61
61: 89 c6 mov %eax,%esi
63: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 6a
6a: b8 00 00 00 00 mov $0x0,%eax
6f: e8 00 00 00 00 callq 74
return 0;
74: b8 00 00 00 00 mov $0x0,%eax
79: c9 leaveq
7a: c3 retq
解读
00 00 00 00
部分,这些都是编译器暂时无法确定的内容.肉眼计算下此时OFFSET
偏移位为 0x16
,0x21
,即下表内容root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -r ./obj/main.o
./obj/main.o: file format elf64-x86-64
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000000000000016 R_X86_64_PC32 .rodata-0x0000000000000004
0000000000000021 R_X86_64_PC32 g_str-0x0000000000000004
0000000000000027 R_X86_64_PC32 g_int-0x0000000000000004
0000000000000030 R_X86_64_PC32 .rodata+0x000000000000000c
000000000000003a R_X86_64_PLT32 printf-0x0000000000000004
0000000000000044 R_X86_64_PLT32 func_int-0x0000000000000004
0000000000000050 R_X86_64_PLT32 func_str-0x0000000000000004
0000000000000057 R_X86_64_PC32 g_str-0x0000000000000004
000000000000005d R_X86_64_PC32 g_int-0x0000000000000004
0000000000000066 R_X86_64_PC32 .rodata+0x0000000000000044
0000000000000070 R_X86_64_PLT32 printf-0x0000000000000004
解读
0x16
,0x21
对应的这些值都是 0,也就是说对于编译器不能确定的地址都这设置为空(0x000000),同时编译器都生成一一对应的记录,该记录告诉链接器在进行链接时要修正这条指令中函数的内存地址,并告知是什么重定位类型,要去哪里找数据填充.
外部全局变量重定位g_str
,g_int
0000000000000021 R_X86_64_PC32 g_str-0x0000000000000004
0000000000000027 R_X86_64_PC32 g_int-0x0000000000000004
---
1e: 48 8b 15 00 00 00 00 mov 0x0(%rip),%rdx # 25
25: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 2b
编译器连g_str在哪个.o文件都不知道,当然更不知道g_str运行时的地址,所以在g.o文件中设置一个重定位,要求后续过程根据"S(g_str内存地址)-A(0x04)",修改main.o镜像中0x21偏移处的值.
函数重定位,重定位类型为 R_X86_64_PLT32
000000000000003a R_X86_64_PLT32 printf-0x0000000000000004
0000000000000044 R_X86_64_PLT32 func_int-0x0000000000000004
0000000000000050 R_X86_64_PLT32 func_str-0x0000000000000004
0000000000000070 R_X86_64_PLT32 printf-0x0000000000000004
---
39: e8 00 00 00 00 callq 3e
43: e8 00 00 00 00 callq 48
同样编译器连``func_int,
printf`在哪个.o文件都不知道,当然更不知道它们的运行时的地址,所以在main.o文件中设置一个重定位,后续将 修改main.o镜像中3a偏移处的值.
另一部分数据由本.o自己提供,如下
root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -sj .rodata ./obj/main.o
./obj/main.o: file format elf64-x86-64
Contents of section .rodata:
0000 6861726d 6f6e7920 6f730000 00000000 harmony os......
0010 6d61696e 20e5bc80 e5a78b20 2d20e585 main ...... - ..
0020 a8e5b180 20675f69 6e74203d 2025642c .... g_int = %d,
0030 20e585a8 e5b18020 675f7374 72203d20 ...... g_str =
0040 25732e0a 00000000 6d61696e 20e7bb93 %s......main ...
0050 e69d9f20 2d20e585 a8e5b180 20675f69 ... - ...... g_i
0060 6e74203d 2025642c 20e585a8 e5b18020 nt = %d, ......
0070 675f7374 72203d20 25732e0a 00 g_str = %s...
解读
13: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # 1a
---
0000000000000016 R_X86_64_PC32 .rodata-0x0000000000000004
因为是局部变量,编译器知道数据放在了 .rodata
区,要求后续过程根据 “S(main.o镜像中.rodata的内存地址)-A(0x04)”,修改main.o镜像中0x16偏移处的值.再分析经过静态链接之后的可执行文件
root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -S ./bin/weharmony
Disassembly of section .text:
0000000000001188 :
void func_str(char *str) {
1188: f3 0f 1e fa endbr64
118c: 55 push %rbp
118d: 48 89 e5 mov %rsp,%rbp
1190: 48 83 ec 10 sub $0x10,%rsp
1194: 48 89 7d f8 mov %rdi,-0x8(%rbp)
g_str = str;
1198: 48 8b 45 f8 mov -0x8(%rbp),%rax
119c: 48 89 05 75 2e 00 00 mov %rax,0x2e75(%rip) # 4018
printf("func_str g_str = %s.\n", g_str);
11a3: 48 8b 05 6e 2e 00 00 mov 0x2e6e(%rip),%rax # 4018
11aa: 48 89 c6 mov %rax,%rsi
11ad: 48 8d 3d 83 0e 00 00 lea 0xe83(%rip),%rdi # 2037 <_IO_stdin_used+0x37>
11b4: b8 00 00 00 00 mov $0x0,%eax
11b9: e8 92 fe ff ff callq 1050
11be: 90 nop
11bf: c9 leaveq
11c0: c3 retq
00000000000011c1 :
#include
#include "part.h"
extern int g_int;
extern char *g_str;
int main() {
11c1: f3 0f 1e fa endbr64
11c5: 55 push %rbp
11c6: 48 89 e5 mov %rsp,%rbp
11c9: 48 83 ec 10 sub $0x10,%rsp
int loc_int = 53;
11cd: c7 45 f4 35 00 00 00 movl $0x35,-0xc(%rbp)
char *loc_str = "harmony os";
11d4: 48 8d 05 75 0e 00 00 lea 0xe75(%rip),%rax # 2050 <_IO_stdin_used+0x50>
11db: 48 89 45 f8 mov %rax,-0x8(%rbp)
printf("main 开始 - 全局 g_int = %d, 全局 g_str = %s.\n", g_int, g_str);
11df: 48 8b 15 32 2e 00 00 mov 0x2e32(%rip),%rdx # 4018
11e6: 8b 05 24 2e 00 00 mov 0x2e24(%rip),%eax # 4010
11ec: 89 c6 mov %eax,%esi
11ee: 48 8d 3d 6b 0e 00 00 lea 0xe6b(%rip),%rdi # 2060 <_IO_stdin_used+0x60>
11f5: b8 00 00 00 00 mov $0x0,%eax
11fa: e8 51 fe ff ff callq 1050
func_int(loc_int);
11ff: 8b 45 f4 mov -0xc(%rbp),%eax
1202: 89 c7 mov %eax,%edi
1204: e8 40 ff ff ff callq 1149
func_str(loc_str);
1209: 48 8b 45 f8 mov -0x8(%rbp),%rax
120d: 48 89 c7 mov %rax,%rdi
1210: e8 73 ff ff ff callq 1188
printf("main 结束 - 全局 g_int = %d, 全局 g_str = %s.\n", g_int, g_str);
1215: 48 8b 15 fc 2d 00 00 mov 0x2dfc(%rip),%rdx # 4018
121c: 8b 05 ee 2d 00 00 mov 0x2dee(%rip),%eax # 4010
1222: 89 c6 mov %eax,%esi
1224: 48 8d 3d 6d 0e 00 00 lea 0xe6d(%rip),%rdi # 2098 <_IO_stdin_used+0x98>
122b: b8 00 00 00 00 mov $0x0,%eax
1230: e8 1b fe ff ff callq 1050
return 0;
1235: b8 00 00 00 00 mov $0x0,%eax
123a: c9 leaveq
123b: c3 retq
123c: 0f 1f 40 00 nopl 0x0(%rax)
root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -s ./bin/weharmony
...省略部分
Contents of section .plt.got:
1040 f30f1efa f2ff25ad 2f00000f 1f440000 ......%./....D..
Contents of section .plt.sec:
1050 f30f1efa f2ff2575 2f00000f 1f440000 ......%u/....D..
Contents of section .data:
4000 00000000 00000000 08400000 00000000 .........@......
4010 33000000 00000000 08200000 00000000 3........ ......
Contents of section .rodata:
2000 01000200 00000000 68656c6c 6f20776f ........hello wo
2010 726c6400 00000000 66756e63 5f696e74 rld.....func_int
2020 20675f69 6e74203d 2025642c 746d7020 g_int = %d,tmp
2030 3d202564 2e0a0066 756e635f 73747220 = %d...func_str
2040 675f7374 72203d20 25732e0a 00000000 g_str = %s......
2050 6861726d 6f6e7920 6f730000 00000000 harmony os......
2060 6d61696e 20e5bc80 e5a78b20 2d20e585 main ...... - ..
2070 a8e5b180 20675f69 6e74203d 2025642c .... g_int = %d,
2080 20e585a8 e5b18020 675f7374 72203d20 ...... g_str =
2090 25732e0a 00000000 6d61696e 20e7bb93 %s......main ...
20a0 e69d9f20 2d20e585 a8e5b180 20675f69 ... - ...... g_i
20b0 6e74203d 2025642c 20e585a8 e5b18020 nt = %d, ......
20c0 675f7374 72203d20 25732e0a 00 g_str = %s...
解读
00 00 00 00
都已经有了实际的数据,例如:char *loc_str = "harmony os";
11d4: 48 8d 05 75 0e 00 00 lea 0xe75(%rip),%rax # 2050 <_IO_stdin_used+0x50>
对应的# 2050 <_IO_stdin_used+0x50>
地址数据正是.rodata
2050位置的 harmony os
1209: 48 8b 45 f8 mov -0x8(%rbp),%rax
120d: 48 89 c7 mov %rax,%rdi
1210: e8 73 ff ff ff callq 1188
callq 1188
1188
正是 func_str
的入口地址void func_str(char *str) {
1188: f3 0f 1e fa endbr64
g_str``g_int
对应的链接地址 0x4018
和 0x4010
1215: 48 8b 15 fc 2d 00 00 mov 0x2dfc(%rip),%rdx # 4018
121c: 8b 05 ee 2d 00 00 mov 0x2dee(%rip),%eax # 4010
由.data
区提供 4000 00000000 00000000 08400000 00000000 .........@......
4010 33000000 00000000 08200000 00000000 3........ ......
0x4010
= 0x33 = 51printf
代码为 callq 1050
1230: e8 1b fe ff ff callq 1050
内容由.plt.sec
区提供,并反汇编该区为 Contents of section .plt.sec:
1050 f30f1efa f2ff2575 2f00000f 1f440000 ......%u/....D..
Disassembly of section .plt.sec:
0000000000001050 :
1050: f3 0f 1e fa endbr64
1054: f2 ff 25 75 2f 00 00 bnd jmpq *0x2f75(%rip) # 3fd0
105b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
注意3fd0
,需要运行时环境提供,加载器动态重定位实现.root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -R ./bin/weharmony
./bin/weharmony: file format elf64-x86-64
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
0000000000003db8 R_X86_64_RELATIVE *ABS*+0x0000000000001140
0000000000003dc0 R_X86_64_RELATIVE *ABS*+0x0000000000001100
0000000000004008 R_X86_64_RELATIVE *ABS*+0x0000000000004008
0000000000004018 R_X86_64_RELATIVE *ABS*+0x0000000000002008
0000000000003fd8 R_X86_64_GLOB_DAT _ITM_deregisterTMCloneTable
0000000000003fe0 R_X86_64_GLOB_DAT __libc_start_main@GLIBC_2.2.5
0000000000003fe8 R_X86_64_GLOB_DAT __gmon_start__
0000000000003ff0 R_X86_64_GLOB_DAT _ITM_registerTMCloneTable
0000000000003ff8 R_X86_64_GLOB_DAT __cxa_finalize@GLIBC_2.2.5
0000000000003fd0 R_X86_64_JUMP_SLOT printf@GLIBC_2.2.5
解读
weharmony
对运行时环境提交的一份外交说明,有了它就可以与国际接轨,入住地球村.3fd0
,其动态链接重定位类型为 R_X86_64_JUMP_SLOT
,它在告诉动态加载器,在运行时环境中找到 printf
并完成动态重定位.在加注过程中,整理出以下文章.内容立足源码,常以生活场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解记忆.说别人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思.更希望让内核变得栩栩如生,倍感亲切.确实有难度,自不量力,但已经出发,回头已是不可能的了.
与代码有bug需不断debug一样,文章和注解内容会存在不少错漏之处,请多包涵,但会反复修正,持续更新,.xx
代表修改的次数,精雕细琢,言简意赅,力求打造精品内容.
v55.xx 鸿蒙内核源码分析(重定位篇) | 与国际接轨的对外部发言人 | 51 .c .h .o
v54.xx 鸿蒙内核源码分析(静态链接篇) | 完整小项目看透静态链接过程 | 51 .c .h .o
v53.xx 鸿蒙内核源码分析(ELF解析篇) | 你要忘了她姐俩你就不是银 | 51 .c .h .o
v52.xx 鸿蒙内核源码分析(静态站点篇) | 五一哪也没去就干了这事 | 51 .c .h .o
v51.xx 鸿蒙内核源码分析(ELF格式篇) | 应用程序入口并不是main | 51 .c .h .o
v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙看这篇或许真的够了 | 51 .c .h .o
v49.xx 鸿蒙内核源码分析(信号消费篇) | 谁让CPU连续四次换栈运行 | 51 .c .h .o
v48.xx 鸿蒙内核源码分析(信号生产篇) | 年过半百,依然活力十足 | 51 .c .h .o
v47.xx 鸿蒙内核源码分析(进程回收篇) | 临终前如何向老祖宗托孤 | 51 .c .h .o
v46.xx 鸿蒙内核源码分析(特殊进程篇) | 龙生龙凤生凤老鼠生儿会打洞 | 51 .c .h .o
v45.xx 鸿蒙内核源码分析(Fork篇) | 一次调用,两次返回 | 51 .c .h .o
v44.xx 鸿蒙内核源码分析(中断管理篇) | 江湖从此不再怕中断 | 51 .c .h .o
v43.xx 鸿蒙内核源码分析(中断概念篇) | 海公公的日常工作 | 51 .c .h .o
v42.xx 鸿蒙内核源码分析(中断切换篇) | 系统因中断活力四射 | 51 .c .h .o
v41.xx 鸿蒙内核源码分析(任务切换篇) | 看汇编如何切换任务 | 51 .c .h .o
v40.xx 鸿蒙内核源码分析(汇编汇总篇) | 汇编可爱如邻家女孩 | 51 .c .h .o
v39.xx 鸿蒙内核源码分析(异常接管篇) | 社会很单纯,复杂的是人 | 51 .c .h .o
v38.xx 鸿蒙内核源码分析(寄存器篇) | 小强乃宇宙最忙存储器 | 51 .c .h .o
v37.xx 鸿蒙内核源码分析(系统调用篇) | 开发者永远的口头禅 | 51 .c .h .o
v36.xx 鸿蒙内核源码分析(工作模式篇) | CPU是韦小宝,七个老婆 | 51 .c .h .o
v35.xx 鸿蒙内核源码分析(时间管理篇) | 谁是内核基本时间单位 | 51 .c .h .o
v34.xx 鸿蒙内核源码分析(原子操作篇) | 谁在为原子操作保驾护航 | 51 .c .h .o
v33.xx 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 51 .c .h .o
v32.xx 鸿蒙内核源码分析(CPU篇) | 整个内核就是一个死循环 | 51 .c .h .o
v31.xx 鸿蒙内核源码分析(定时器篇) | 哪个任务的优先级最高 | 51 .c .h .o
v30.xx 鸿蒙内核源码分析(事件控制篇) | 任务间多对多的同步方案 | 51 .c .h .o
v29.xx 鸿蒙内核源码分析(信号量篇) | 谁在负责解决任务的同步 | 51 .c .h .o
v28.xx 鸿蒙内核源码分析(进程通讯篇) | 九种进程间通讯方式速揽 | 51 .c .h .o
v27.xx 鸿蒙内核源码分析(互斥锁篇) | 比自旋锁丰满的互斥锁 | 51 .c .h .o
v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁当立贞节牌坊 | 51 .c .h .o
v25.xx 鸿蒙内核源码分析(并发并行篇) | 听过无数遍的两个概念 | 51 .c .h .o
v24.xx 鸿蒙内核源码分析(进程概念篇) | 进程在管理哪些资源 | 51 .c .h .o
v23.xx 鸿蒙内核源码分析(汇编传参篇) | 如何传递复杂的参数 | 51 .c .h .o
v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班 | 51 .c .h .o
v21.xx 鸿蒙内核源码分析(线程概念篇) | 是谁在不断的折腾CPU | 51 .c .h .o
v20.xx 鸿蒙内核源码分析(用栈方式篇) | 程序运行场地由谁提供 | 51 .c .h .o
v19.xx 鸿蒙内核源码分析(位图管理篇) | 谁能一分钱分两半花 | 51 .c .h .o
v18.xx 鸿蒙内核源码分析(源码结构篇) | 内核每个文件的含义 | 51 .c .h .o
v17.xx 鸿蒙内核源码分析(物理内存篇) | 怎么管理物理内存 | 51 .c .h .o
v16.xx 鸿蒙内核源码分析(内存规则篇) | 内存管理到底在管什么 | 51 .c .h .o
v15.xx 鸿蒙内核源码分析(内存映射篇) | 虚拟内存虚在哪里 | 51 .c .h .o
v14.xx 鸿蒙内核源码分析(内存汇编篇) | 谁是虚拟内存实现的基础 | 51 .c .h .o
v13.xx 鸿蒙内核源码分析(源码注释篇) | 鸿蒙必定成功,也必然成功 | 51 .c .h .o
v12.xx 鸿蒙内核源码分析(内存管理篇) | 虚拟内存全景图是怎样的 | 51 .c .h .o
v11.xx 鸿蒙内核源码分析(内存分配篇) | 内存有哪些分配方式 | 51 .c .h .o
v10.xx 鸿蒙内核源码分析(内存主奴篇) | 皇上和奴才如何相处 | 51 .c .h .o
v09.xx 鸿蒙内核源码分析(调度故事篇) | 用故事说内核调度过程 | 51 .c .h .o
v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 百篇博客分析 | 51 .c .h .o
v07.xx 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 51 .c .h .o
v06.xx 鸿蒙内核源码分析(调度队列篇) | 内核有多少个调度队列 | 51 .c .h .o
v05.xx 鸿蒙内核源码分析(任务管理篇) | 任务池是如何管理的 | 51 .c .h .o
v04.xx 鸿蒙内核源码分析(任务调度篇) | 任务是内核调度的单元 | 51 .c .h .o
v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁的贡献最大 | 51 .c .h .o
v02.xx 鸿蒙内核源码分析(进程管理篇) | 谁在管理内核资源 | 51 .c .h .o
v01.xx 鸿蒙内核源码分析(双向链表篇) | 谁是内核最重要结构体 | 51 .c .h .o
看系列篇文章会常看到 51 .c .h .o
,希望这对大家阅读不会造成影响.
分别对应以下四个站点的首个字符,感谢这些站点一直以来对系列篇的支持和推荐,尤其是 oschina gitee ,很喜欢它的界面风格,简洁大方,让人感觉到开源的伟大!
而巧合的是.c .h .o
是C语言的头/源/目标文件,这就很有意思了,冥冥之中似有天数,将这四个宝贝以这种方式融合在一起. 51 .c .h .o
, 我要CHO ,嗯嗯,hin 顺口 : )
百万汉字注解 >> 精读鸿蒙源码,中文注解分析, 深挖地基工程,大脑永久记忆,四大码仓每日同步更新< gitee | github | csdn | coding >
百篇博客分析 >> 故事说内核,问答式导读,生活式比喻,表格化说明,图形化展示,主流站点定期更新中< 51cto | csdn | harmony | osc >
热爱是所有的理由和答案 - turing
原创不易,欢迎转载,但麻烦请注明出处.