鸿蒙内核源码分析(重定位篇) | 与国际接轨

news2024/11/26 9:51:44

一个程序从源码到被执行,当中经历了3个过程:

  • 编译:将.c文件编译成.o文件,不关心.o文件之间的联系.
  • 静态链接:将所有.o文件合并成一个.so或.out文件,处理所有.o文件节区在目标文件中的布局.
  • 动态链接:将.so或a.out文件加载到内存,处理加载文件在的内存中的布局.

什么是重定位

重定位就是把程序的逻辑地址空间变换成内存中的实际物理地址空间的过程。它是实现多道程序在内存中同时运行的基础。重定位有两种,分别是动态重定位与静态重定位。

  • 1.静态重定位:即在程序装入内存的过程中完成,是指在程序开始运行前,程序中的各个地址有关的项均已完成重定位,地址变换通常是在装入时一次完成的,以后不再改变,故称为静态重定位。也就是在生成可执行/共享目标文件的同时已完成地址的静态定位,它解决了可执行文件/共享目标文件的内部矛盾.
  • 2.动态重定位:它不是在程序装入内存时完成的,而是CPU每次访问内存时 由动态地址变换机构(硬件)自动进行把相对地址转换为绝对地址。动态重定位需要软件和硬件相互配合完成。也就是说可执行文件/共享目标文件的外部矛盾需要外部环境解决,它向外提供了一份入住地球村的外交说明.即本篇最后部分内容.

重定位十种类型

  • 重定位有10种类型,在实际中请对号入座,这些类型部分在本篇能见到,如下:

解读

  • fPIC的全称是 Position Independent Code, 用于生成位置无关代码。

objdump命令

objdump命令是Linux下的反汇编目标文件或者可执行文件的命令,它以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息.本篇将用它说明静态重定位的实现细节和动态重定位前置条件准备.先整体走读下objdump命令

root@5e3abe332c5a:/home/docker/test4harmony/54# objdump
Usage: objdump <option(s)> <file(s)>
 Display information from object <file(s)>.
 At least one of the following switches must be given:
  -a, --archive-headers    Display archive header information
  -f, --file-headers       Display the contents of the overall file header
  -p, --private-headers    Display object format specific file header contents
  -P, --private=OPT,OPT... Display object format specific contents
  -h, --[section-]headers  Display the contents of the section headers
  -x, --all-headers        Display the contents of all headers
  -d, --disassemble        Display assembler contents of executable sections
  -D, --disassemble-all    Display assembler contents of all sections
      --disassemble=<sym>  Display assembler contents from <sym>
  -S, --source             Intermix source code with disassembly
      --source-comment[=<txt>] Prefix lines of source code with <txt>
  -s, --full-contents      Display the full contents of all sections requested
  -g, --debugging          Display debug information in object file
  -e, --debugging-tags     Display debug information using ctags style
  -G, --stabs              Display (in raw form) any STABS info in the file
  -W[lLiaprmfFsoRtUuTgAckK] or
  --dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
          =frames-interp,=str,=loc,=Ranges,=pubtypes,
          =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,
          =addr,=cu_index,=links,=follow-links]
                           Display DWARF info in the file
  --ctf=SECTION            Display CTF info from SECTION
  -t, --syms               Display the contents of the symbol table(s)
  -T, --dynamic-syms       Display the contents of the dynamic symbol table
  -r, --reloc              Display the relocation entries in the file
  -R, --dynamic-reloc      Display the dynamic relocation entries in the file
  @<file>                  Read options from <file>
  -v, --version            Display this program's version number
  -i, --info               List object formats and architectures supported
  -H, --help               Display this information

objdump -S ./obj/main.o

main.o是个可重定位文件,通过 readelf 可知

root@5e3abe332c5a:/home/docker/test4harmony/54# readelf -h ./obj/main.o 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0

root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -S ./obj/main.o 
./obj/main.o:     file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:     
#include <stdio.h>
#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 <main+0x1a>
  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 <main+0x25>
  25:   8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 2b <main+0x2b>
  2b:   89 c6                   mov    %eax,%esi
  2d:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # 34 <main+0x34>
  34:   b8 00 00 00 00          mov    $0x0,%eax
  39:   e8 00 00 00 00          callq  3e <main+0x3e>
        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 <main+0x48>
        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 <main+0x54>
        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 <main+0x5b>
  5b:   8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 61 <main+0x61>
  61:   89 c6                   mov    %eax,%esi
  63:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # 6a <main+0x6a>
  6a:   b8 00 00 00 00          mov    $0x0,%eax
  6f:   e8 00 00 00 00          callq  74 <main+0x74>
        return 0;
  74:   b8 00 00 00 00          mov    $0x0,%eax
  79:   c9                      leaveq
  7a:   c3                      retq

解读

  • 注意那些 00 00 00 00部分,这些都是编译器暂时无法确定的内容.肉眼计算下此时OFFSET偏移位为 0x16,0x21,即下表内容

objdump -r ./obj/main.o

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 <main+0x25>
25:   8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 2b <main+0x2b>

编译器连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 <main+0x3e>
43:   e8 00 00 00 00          callq  48 <main+0x48>

同样编译器连``func_int,printf`在哪个.o文件都不知道,当然更不知道它们的运行时的地址,所以在main.o文件中设置一个重定位,后续将 修改main.o镜像中3a偏移处的值.

  • 另一部分数据由本.o自己提供,如下

objdump -sj .rodata ./obj/main.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 <main+0x1a>
---
0000000000000016 R_X86_64_PC32     .rodata-0x0000000000000004

因为是局部变量,编译器知道数据放在了 .rodata区,要求后续过程根据 “S(main.o镜像中.rodata的内存地址)-A(0x04)”,修改main.o镜像中0x16偏移处的值.

再分析经过静态链接之后的可执行文件

objdump -S ./bin/weharmony

root@5e3abe332c5a:/home/docker/test4harmony/54# objdump -S ./bin/weharmony 
Disassembly of section .text:
0000000000001188 <func_str>:
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 <g_str>
        printf("func_str g_str = %s.\n", g_str);
    11a3:       48 8b 05 6e 2e 00 00    mov    0x2e6e(%rip),%rax        # 4018 <g_str>
    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 <printf@plt>
    11be:       90                      nop
    11bf:       c9                      leaveq
    11c0:       c3                      retq

00000000000011c1 <main>:
#include <stdio.h>
#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 <g_str>
    11e6:       8b 05 24 2e 00 00       mov    0x2e24(%rip),%eax        # 4010 <g_int>
    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 <printf@plt>
        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_int>
        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 <func_str>
        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 <g_str>
    121c:       8b 05 ee 2d 00 00       mov    0x2dee(%rip),%eax        # 4010 <g_int>
    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 <printf@plt>
        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...

解读

  • main.o中被重定位的部分不再是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

  • 看main()中的
void func_str(char *str) {
    1188:       f3 0f 1e fa             endbr64
  • 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 <g_str>
121c:       8b 05 ee 2d 00 00       mov    0x2dee(%rip),%eax        # 4010 <g_int>

由.data区提供

  4000 00000000 00000000 08400000 00000000  .........@......
  4010 33000000 00000000 08200000 00000000  3........ ......

0x4010 = 0x33 = 51

  • main函数中调用 printf代码为 callq 1050
  1230:       e8 1b fe ff ff          callq  1050 <printf@plt>

内容由.plt.sec区提供,并反汇编该区为

  Contents of section .plt.sec:
  1050 f30f1efa f2ff2575 2f00000f 1f440000  ......%u/....D..

  Disassembly of section .plt.sec:
  0000000000001050 <printf@plt>:
      1050:       f3 0f 1e fa             endbr64
      1054:       f2 ff 25 75 2f 00 00    bnd jmpq *0x2f75(%rip)        # 3fd0 <printf@GLIBC_2.2.5>
      105b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

注意3fd0,需要运行时环境提供,加载器动态重定位实现.

  • 总结下来就是 weharmony 已完成了所有.o文件的静态重定位部分, 组合成一个新的可执行文件,其中只还有动态链接部分尚未完成,因为那需要运行时重定位地址.如下:

objdump -R ./bin/weharmony

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并完成动

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2060865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将所有PPT中的字体颜色白色改成黑色---使用AI提高效率

背景 在工作中&#xff0c;遇到一个PPT&#xff0c;老板需求&#xff0c;将PPT页面的所有的字体从白色改成黑色&#xff0c; 检查了发现&#xff0c;这个ppt有几个问题&#xff0c;没有使用母版&#xff0c;都是每一页进行编写&#xff0c; 一共500多页&#xff0c; 如果每个…

Markdown中使用 LaTeX 绘图 -- TikZ

Markdown中使用 LaTeX 绘图 -- TikZ 1 介绍1.1 概述1.2 与其他图包对比 2 示例 & 学习[The TikZ and PGF Packages](https://tikz.dev/)[Graphics with TikZ in LaTeX](https://tikz.net/)[TikZ PGF Manual](https://www.bu.edu/math/files/2013/08/tikzpgfmanual.pdf)[在 …

中科亿海微伺服控制FOC解决方案

随着科技的不断进步和应用的不断扩展&#xff0c;电机控制技术的需求也在不断增加&#xff0c;主要的电机控制需求包括高精度控制、高效率、高可靠性和智能化等。 FOC&#xff08;磁场定向控制&#xff09;&#xff0c;也被称作VC&#xff08;矢量控制&#xff09;&#xff0c…

从用户体验说起,集运系统需要哪些重要的功能?

良好的用户体验是服务成功的关键&#xff0c;更是客户持续选择的理由。用户体验层面最简单的表达其实就是&#xff1a;别让我等、别让我想、别让我烦。 在当今时代&#xff0c;用户的期望正在不断提高&#xff0c;他们追求快捷、高效和透明的服务。因此&#xff0c;集运系统在…

生信圆桌x生信菜鸟团:生物信息学初学者的交流与成长社区

生信菜鸟团是一个专门为生物信息学初学者和爱好者打造的在线社区&#xff0c;致力于为广大生信学习者提供一个分享知识、交流经验、共同成长的平台。随着生物信息学在各大领域的快速发展&#xff0c;越来越多的研究者和学生开始涉足这一领域&#xff0c;但生信知识的广度和深度…

人才流失预测项目

在本项目中&#xff0c;通过数据科学和AI的方法&#xff0c;分析挖掘人力资源流失问题&#xff0c;并基于机器学习构建解决问题的方法&#xff0c;并且&#xff0c;我们通过对AI模型的反向解释&#xff0c;可以深入理解导致人员流失的主要因素&#xff0c;HR部门也可以根据分析…

备战秋招60天算法挑战,Day22

题目链接&#xff1a; https://leetcode.cn/problems/missing-number/ 视频题解&#xff1a; https://www.bilibili.com/video/BV1HS42197Hc/ LeetCode 268.丢失的数字 题目描述 给定一个包含 [0, n] 中 n 个数的数组 nums &#xff0c;找出 [0, n] 这个范围内没有出现在数组…

基于Python flask的岗位招聘数据分析系统,应用Python、Flask框架、Pyecharts、Wordcloud等技术

基于Python Flask的岗位招聘数据分析系统旨在为企业人力资源部门和求职者提供一个全面的数据分析平台&#xff0c;通过对招聘数据的深度挖掘和可视化展示&#xff0c;帮助用户做出更明智的决策。该系统采用了Python、Flask框架&#xff0c;并结合Pyecharts、Wordcloud等技术&am…

Matplotlib基本操作

1.什么是Matplotlib matplotlib 是一个广泛使用的 Python 图形库&#xff0c;用于生成静态、动态和交互式的可视化图表。它最初由 John D. Hunter 创建&#xff0c;并首次发布于2003年。matplotlib 提供了一个面向对象的 API&#xff0c;允许用户创建多种类型的图表&#xff0c…

[JavaScript版本五子棋小游戏]

目录 全部运行代码&#xff1a;五子棋游戏的基本步骤&#xff1a;代码剖析&#xff1a;1. 初始化游戏界面2. 管理游戏状态3. 玩家交互4. 电脑AI5. 胜负判定6. 游戏控制 本文通过实现一个基本的五子棋游戏&#xff0c;展示了如何使用HTML、CSS和JavaScript来构建一个简单的交互式…

ATGM332D-F8N低功耗、小尺寸单北斗多频定位导航模块规格书

ATGM332D-F8N主要 特征 &#xff1a; 1、多频点单北斗接收机 支持B1C独立定位通道数目&#xff1a;176通道支持北斗二号、北斗三号支持B1I、B1C、B2I、B3I、B2a、B2b 定位精度 单点定位精度&#xff1a;<1.0mCEP50推算定位误差&#xff1a;<3&#xff05;&#xff08;定位…

伦敦银行情的软件有什么选择?

普通投资者做伦敦银交易&#xff0c;多以技术分析为主、基本分析为辅的方法作为自己的交易策略&#xff0c;既然提到技术分析&#xff0c;那么伦敦银行情的软件就至关重要&#xff0c;因为我们需要通过这些软件才能看到行情并进行分析&#xff0c;那看伦敦银行情的软件有什么好…

2024.8.21

130124202408211006 DATE #:20240821 ITEM #:DOC WEEK #:WEDNESDAY DAIL #:捌月拾捌 TAGS < BGM "琴师--要不要买菜" > < theme oi-contest > < [NULL] > < [空] > < [空] > 此情可待成追忆&#xff0c;只是当时已惘然 -- 《锦瑟》…

「OC」视图控制器的懒加载策略

「OC」视图控制器的懒加载策略 文章目录 「OC」视图控制器的懒加载策略懒加载懒加载的优点常见的懒加载实现方法使用懒加载的注意事项 控制器的懒加载参考资料 懒加载 懒加载&#xff08;Lazy Loading&#xff09;是一种设计模式&#xff0c;其核心思想是在需要时才进行对象的…

Verilog刷题笔记55

题目&#xff1a; Exams/ece241 2014 q5a You are to design a one-input one-output serial 2’s complementer Moore state machine. The input (x) is a series of bits (one per clock cycle) beginning with the least-significant bit of the number, and the output (Z)…

更快更强,SLS 推出高性能 SPL 日志查询模式

作者&#xff1a;无哲 引言 随着数字化进程的持续深化&#xff0c;可观测性一直是近年来非常火热的话题&#xff0c;在可观测的三大支柱 Log/Trace/Metric 中&#xff0c;日志&#xff08;Log&#xff09;数据一般是最为常见的&#xff0c;企业迈向可观测性的第一步&#xff…

《黑神话:悟空》总销量已破 450 万份,总销售额超过15亿元,对于单机游戏来说,这一成绩意味着什么?

《黑神话&#xff1a;悟空》总销量突破450万份&#xff0c;总销售额超过15亿元&#xff0c;意味着几个关键点&#xff1a; 市场认可度高&#xff1a;这样的销量和销售额表明游戏受到了广泛的玩家欢迎&#xff0c;市场认可度极高。对于单机游戏而言&#xff0c;这代表了其在游戏…

深入浅出:你需要了解的用户数据报协议(UDP)

文章目录 **UDP概述****1. 无连接性****2. 尽最大努力交付****3. 面向报文****4. 多种交互通信支持****5. 较少的首部开销** **UDP报文的首部格式****详细解释每个字段** **UDP的多路分用模型****多路分用的实际应用** **检验和的计算方法****伪首部的详细内容****检验和计算步…

算法4:前缀和(下)

文章目录 和为K的子数组和可被k整除的子数组连续数组矩阵区域和 一定要看懂算法原理之后写代码&#xff0c;博主大概率因注意力不够&#xff0c;看了好多遍&#xff0c;才看懂原理细节。 切记&#xff0c;不彻底懂原理&#xff0c;千万别看代码 和为K的子数组 class Solution …

K8s部署安装

目录 一.K8s简介 1.Kubernetes 的关键概念 2.Kubernetes 的功能优势 3.节点&#xff08;Node&#xff09; 4.组件&#xff08;Component&#xff09; 二.Kubernetes集群架构 三.安装部署环境 1.初始化系统环境 2.安装容器引擎 3. 安装containerd 4.安装crictl工具 5…