动态链接库中函数的地址确定---PLT和GOT

2023-11-13

分类: C/C++

      前面写过动态链接库 延迟绑定的一篇博文,那篇文章我非常喜欢,但是当时刚搞清楚,自己写的比较凌乱,我最近学习了Ulrich Drepper的How to write share library,学习了几篇其他的讲述动态链接的文章,再次整理了这篇文章。
    有一个问题是我们调用了动态链接库里面的函数,我们怎么知道动态链接库里面的函数的地址呢?事实上,直到我们第一次调用这个函数,我们并不知道这个函数的地址,这个功能要做延迟绑定 lazy bind。 因为程序的分支很多,并不是所有的分支都能跑到,想想我们的异常处理,异常处理分支的动态链接库里面的函数也许永远跑不到,所以,一上来就解析所有出现过的动态库里面的函数是个浪费的办法,降低性能并且没有必要。
    下面我们看下延迟绑定的效果。我写了个程序,先睡15s,然后pthread_create 一个线程。我们用LD_DEBUG观察符号的解析。

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<pthread.h>


  4. void* myfunc()
  5. {
  6.         while(1)
  7.         {
  8.          sleep(10);
  9.         }
  10.         return NULL;
  11. }



  12. int main()
  13. {
  14.         sleep(15);
  15.         pthread_t tid = 0;
  16.         int ret = pthread_create(&tid,NULL,myfunc,NULL);
  17.         if(ret)
  18.         {
  19.                 fprintf(stderr,"pthread create failed %m \n");
  20.                 return -1;
  21.         }

  22.         ret = pthread_join(tid,NULL);
  23.         if(ret)
  24.         {
  25.                 fprintf(stderr,"pthread join failed %m\n");
  26.                 return -2;
  27.         }

  28.         return 0;
  29. }


  1. root@libin:~/program/C/plt_got# LD_DEBUG=symbols ./test
  2. 2849:symbol=_res;  lookup in file=./test [0]
  3. 2849:symbol=_res;  lookup in file=/lib/tls/i686/cmov/libpthread.so.0 [0]
  4. 2849:symbol=_res;  lookup in file=/lib/tls/i686/cmov/libc.so.6 [0]
  5. 2849:symbol=_IO_file_close;  lookup in file=./test [0]
  6. 2849:symbol=_IO_file_close;  lookup in file=/lib/tls/i686/cmov/libpthread.so.0 [0]
  7. 2849:symbol=_IO_file_close;  lookup in file=/lib/tls/i686/cmov/libc.so.6 [0]
  8. 2849:symbol=rpc_createerr;  lookup in file=./test [0]
  9. 2849:symbol=rpc_createerr;  lookup in file=/lib/tls/i686/cmov/libpthread.so.0 [0]
  10. 2849:symbol=rpc_createerr;  lookup in file=/lib/tls/i686/cmov/libc.so.6 [0]

...................
 2849:   transferring control: ./test
 2849:
 2849:   symbol=sleep;  lookup in file=./test [0]
 2849:   symbol=sleep;  lookup in file=/lib/tls/i686/cmov/libpthread.so.0 [0]
 2849:   symbol=sleep;  lookup in file=/lib/tls/i686/cmov/libc.so.6 [0]
===================================================================================
     然后停了15s,才解析出pthread_create的地址,由此可见,得确是运行时重定位,知道用到这个函数pthread_create才真正去找这个函数的地址。

  1. 2849:    
  2. 2849:    symbol=sleep; lookup in file=./test [0]
  3. 2849:    symbol=sleep; lookup in file=/lib/tls/i686/cmov/libpthread.so.[0]
  4. 2849:    symbol=sleep; lookup in file=/lib/tls/i686/cmov/libc.so.[0]
  5. ===================================================================================
  6. 2849:    symbol=pthread_create; lookup in file=./test [0]
  7. 2849:    symbol=pthread_create; lookup in file=/lib/tls/i686/cmov/libpthread.so.[0]
  8. 2849:    symbol=__getpagesize; lookup in file=./test [0]
  9. 2849:    symbol=__getpagesize; lookup in file=/lib/tls/i686/cmov/libpthread.so.[0]
  10. 2849:    symbol=__getpagesize; lookup in file=/lib/tls/i686/cmov/libc.so.[0]
  11. 2849:    symbol=mmap; lookup in file=./test [0]
  12. 2849:    symbol=mmap; lookup in file=/lib/tls/i686/cmov/libpthread.so.[0]
  13. 2849:    symbol=mmap; lookup in file=/lib/tls/i686/cmov/libc.so.[0]
     真正动态库中函数地址的解析是第一次调用的时候做的,然后如果再次用到动态库的解析过的函数,就直接用第一次解析的结果。很自然的想法就是,一定有地方存储函数的地址,否则第一次解析出来的结果,第二次调用也没法利用。 这个存储动态库函数的地方就要GOT,Global Offset Table。 OK,我们可以想象,如果我的程序里面用到了6个动态库里面的函数,那个这个GOT里面就应该存有6个条目,每个条目里面存储着对应函数的地址。事实的确是这样:

  1. root@libin:~/program/C/plt_got# readelf -r test

  2. Relocation section '.rel.dyn' at offset 0x394 contains 2 entries:
  3. Offset Info Type Sym.Value Sym. Name
  4. 08049ff0 00000206 R_386_GLOB_DAT 00000000 __gmon_start__
  5. 0804a020 00000905 R_386_COPY 0804a020 stderr

  6. Relocation section '.rel.plt' at offset 0x3a4 contains 6 entries:
  7. Offset Info Type Sym.Value Sym. Name
  8. 0804a000 00000107 R_386_JUMP_SLOT 00000000 pthread_join
  9. 0804a004 00000207 R_386_JUMP_SLOT 00000000 __gmon_start__
  10. 0804a008 00000407 R_386_JUMP_SLOT 00000000 __libc_start_main
  11. 0804a00c 00000507 R_386_JUMP_SLOT 00000000 fprintf
  12. 0804a010 00000607 R_386_JUMP_SLOT 00000000 pthread_create
  13. 0804a014 00000707 R_386_JUMP_SLOT 00000000 sleep
     我们看到了有全局变量stderr和__gmon_start__需要重定位,这些本文并不关心。下面是需要重定位的函数,可以看出,我们调用动态库里面的函数都在这了,fprintf是Glibc库的,pthread_create是pthread库的等等。
 
   动态库里面需要重定位的函数在.got.plt这个段里面,我们看下:
     .got.plt这个段的起始地址是0x8049ff4。 .got.plt这个section大小为0x24 = 36,可是我们只有6个需要解析地址的function,4*6=24个字节,只需要24个字节就能存放这6个函数指针。多出来的12个字节是dynamic段地址,ModuleID 和 _dl_runtime_resolve的地址,如下图所示
     OK 。我们看一下:

  1. (gdb) b main
  2. Breakpoint 1 at 0x8048551: file test.c, line 19.
  3. (gdb) r
  4. Starting program: /home/libin/program/C/plt_got/test
  5. [Thread debugging using libthread_db enabled]

  6. Breakpoint 1, main () at test.c:19
  7. 19 sleep(15);
  8. (gdb) x/24x 0x8049ff4
  9. 0x8049ff4 <_GLOBAL_OFFSET_TABLE_>: 0x08049f18 0x0012c8f8 0x00123270 0x0804841a
  10. 0x804a004 <_GLOBAL_OFFSET_TABLE_+16>: 0x0804842a 0x0015daf0 0x0804844a 0x0804845a
  11. 0x804a014 <_GLOBAL_OFFSET_TABLE_+32>: 0x0804846a 0x00000000 0x00000000 0x0029c580
  12. 0x804a024 <completed.7021>: 0x00000000 0x00000000 0x00000000 0x00000000
  13. 0x804a034: 0x00000000 0x00000000 0x00000000 0x00000000
  14. 0x804a044: 0x00000000 0x00000000 0x00000000 0x00000000
蓝色的0x0849f18是dynamic段的地址

  1. [21] .dynamic DYNAMIC 08049f18 000f18 0000d8 08 WA 7 0 4
 
接下来,我们要分析PLT 和GOT的关系了。

  1. (gdb) disas main
  2. ....

  3. 0x0804857e <+54>: lea 0x1c(%esp),%eax
  4. 0x08048582 <+58>: mov %eax,(%esp)
  5. 0x08048585 <+61>: call 0x8048454 <pthread_create@plt>
  6. 0x0804858a <+66>: mov %eax,0x18(%esp)
  7. 0x0804858e <+70>: cmpl $0x0,0x18(%esp)
  8. .....
 
    要执行pthread_create 函数,跳到PLT部分。

  1. libin@libin:~/program/C/plt_got$ objdump -dj .plt test

  2. test: file format elf32-i386


  3. Disassembly of section .plt:

  4. 08048404 <pthread_join@plt-0x10>:
  5. 8048404: ff 35 f8 9f 04 08 pushl 0x8049ff8
  6. 804840a: ff 25 fc 9f 04 08 jmp *0x8049ffc
  7. 8048410: 00 00 add %al,(%eax)
  8. ...

  9. 08048414 <pthread_join@plt>:
  10. 8048414: ff 25 00 a0 04 08 jmp *0x804a000
  11. 804841a: 68 00 00 00 00 push $0x0
  12. 804841f: e9 e0 ff ff ff jmp 8048404 <_init+0x30>

  13. 08048424 <__gmon_start__@plt>:
  14. 8048424: ff 25 04 a0 04 08 jmp *0x804a004
  15. 804842a: 68 08 00 00 00 push $0x8
  16. 804842f: e9 d0 ff ff ff jmp 8048404 <_init+0x30>

  17. 08048434 <__libc_start_main@plt>:
  18. 8048434: ff 25 08 a0 04 08 jmp *0x804a008
  19. 804843a: 68 10 00 00 00 push $0x10
  20. 804843f: e9 c0 ff ff ff jmp 8048404 <_init+0x30>

  21. 08048444 <fprintf@plt>:
  22. 8048444: ff 25 0c a0 04 08 jmp *0x804a00c
  23. 804844a: 68 18 00 00 00 push $0x18
  24. 804844f: e9 b0 ff ff ff jmp 8048404 <_init+0x30>

  25. 08048454 <pthread_create@plt>:
  26. 8048454: ff 25 10 a0 04 08 jmp *0x804a010
  27. 804845a: 68 20 00 00 00 push $0x20
  28. 804845f: e9 a0 ff ff ff jmp 8048404 <_init+0x30>

  29. 08048464 <sleep@plt>:
  30. 8048464: ff 25 14 a0 04 08 jmp *0x804a014
  31. 804846a: 68 28 00 00 00 push $0x28
  32. 804846f: e9 90 ff ff ff jmp 8048404 <_init+0x30>
    PLT部分认为pthread_create函数存放在GOT,0x804a010是GOT里面的一个条目,这个条目存储着pthread_create函数的地址。当第二次以至于第N次调用pthead_create的时候,的的确确存放着pthread_create的地址,但是第一次不行,第一次这个条目里面还没记录这个地址。那么这个条目记录的是什么呢?

  1. (gdb) x/10i 0x8048454
  2. 0x8048454 <pthread_create@plt>: jmp *0x804a010
  3. 0x804845a <pthread_create@plt+6>: push $0x20
  4. 0x804845f <pthread_create@plt+11>: jmp 0x8048404
  5. 0x8048464 <sleep@plt>: jmp *0x804a014
  6. 0x804846a <sleep@plt+6>: push $0x28
  7. 0x804846f <sleep@plt+11>: jmp 0x8048404
  8. 0x8048474: add %al,(%eax)
  9. 0x8048476: add %al,(%eax)
  10. 0x8048478: add %al,(%eax)
  11. 0x804847a: add %al,(%eax)
  12. (gdb) x/10x 0x804a010
  13. 0x804a010 <_GLOBAL_OFFSET_TABLE_+28>: 0x0804845a 0x0804846a 0x00000000 0x00000000
  14. 0x804a020 <stderr@@GLIBC_2.0>: 0x0029c580 0x00000000 0x00000000 0x00000000
  15. 0x804a030: 0x00000000 0x00000000
    0x804a010这个地址最终应该记录的是pthread_create的地址,但是目前还不是,记录的是0x084845a


  1.  08048454 <pthread_create@plt>:
  2.  8048454:ff 25 10 a0 04 08    jmp    *0x804a010
  3.  804845a:68 20 00 00 00       push   $0x20
  4.  804845f:e9 a0 ff ff ff       jmp    8048404 <_init+0x30>
    从PLT跳到GOT 找地址,但是第一次找的时候,并不是pthread_create的地址,而是又跳回来PLT,我们看到push了0x20之后,跳到了0x8048404。 每一个PLT的代码段,都是push了一个值之后,跳到了0x8048404。大家可以去上面的图验证。
 

    接下来,我们看0x8048404存放的是啥指令:

  1. (gdb) x/10i 0x8048404
  2.    0x8048404:    pushl 0x8049ff8
  3.    0x804840a:    jmp *0x8049ffc
  4.    0x8048410:    add %al,(%eax)
  5.    0x8048412:    add %al,(%eax)
  6.    0x8048414 <pthread_join@plt>:    jmp *0x804a000
  7.    0x804841a <pthread_join@plt+6>:    push $0x0
  8.    0x804841f <pthread_join@plt+11>:    jmp 0x8048404
  9.    0x8048424 <__gmon_start__@plt>:    jmp *0x804a004
  10.    0x804842a <__gmon_start__@plt+6>:    push $0x8
  11.    0x804842f <__gmon_start__@plt+11>:    jmp 0x8048404

  1. (gdb) x/10x 0x8049ffc
  2. 0x8049ffc <_GLOBAL_OFFSET_TABLE_+8>:    0x00123270    0x0804841a    0x0804842a    0x0015daf0
  3. 0x804a00c <_GLOBAL_OFFSET_TABLE_+24>:    0x0804844a    0x0804845a    0x0804846a    0x00000000
  4. 0x804a01c <__dso_handle>:    0x00000000    0x0029c580
  5. (gdb) x/10i 0x00123270
  6.    0x123270 <_dl_runtime_resolve>:    push %eax
  7.    0x123271 <_dl_runtime_resolve+1>:    push %ecx
  8.    0x123272 <_dl_runtime_resolve+2>:    push %edx
  9.    0x123273 <_dl_runtime_resolve+3>:    mov 0x10(%esp),%edx
  10.    0x123277 <_dl_runtime_resolve+7>:    mov 0xc(%esp),%eax
  11.    0x12327b <_dl_runtime_resolve+11>:    call 0x11d5a0 <_dl_fixup>
  12.    0x123280 <_dl_runtime_resolve+16>:    pop %edx
  13.    0x123281 <_dl_runtime_resolve+17>:    mov (%esp),%ecx
  14.    0x123284 <_dl_runtime_resolve+20>:    mov %eax,(%esp)
  15.    0x123287 <_dl_runtime_resolve+23>:    mov 0x4(%esp),%eax
    我们看到0x8049ffc就是GOT的第三项,前文提到的dl_runtime_resolve的地址。这个函数将帮助我们将pthread_create函数地址定位,并且填入GOT表的相应位置 0x804a010。
    我们watch下GOT pthread_create对应条目,看下这个条目啥时候变化:

  1. (gdb) b main
  2. Breakpoint 1 at 0x8048551: file test.c, line 19.
  3. (gdb) r
  4. Starting program: /home/libin/program/C/plt_got/test 
  5. [Thread debugging using libthread_db enabled]

  6. Breakpoint 1, main () at test.c:19
  7. 19     sleep(15);
  8. (gdb) watch *0x804a010
  9. Hardware watchpoint 2: *0x804a010
  10. (gdb) c
  11. Continuing.
  12. Hardware watchpoint 2: *0x804a010

  13. Old value = 134513754
  14. New value = 1260912
  15. _dl_fixup (l=<value optimized out>, reloc_arg=<value optimized out>) at dl-runtime.c:155
  16. 155    dl-runtime.c: 没有那个文件或目录.
  17.     in dl-runtime.c
  18. (gdb) bt
  19. #0 _dl_fixup (l=<value optimized out>, reloc_arg=<value optimized out>) at dl-runtime.c:155
  20. #1 0x00123280 in _dl_runtime_resolve () at ../sysdeps/i386/dl-trampoline.S:37
  21. #2 0x0804858a in main () at test.c:21
  22. (gdb)

    看到了,是_dl_runtime_resolve调用了_dl_fixup修改了GOT的对应条目。

  1. (gdb) x/10i 1260912
  2.    0x133d70 <__pthread_create_2_1>:    push %ebp
  3.    0x133d71 <__pthread_create_2_1+1>:    mov %esp,%ebp
  4.    0x133d73 <__pthread_create_2_1+3>:    push %edi
  5.    0x133d74 <__pthread_create_2_1+4>:    push %esi
  6.    0x133d75 <__pthread_create_2_1+5>:    push %ebx
  7.    0x133d76 <__pthread_create_2_1+6>:    call 0x132340 <__i686.get_pc_thunk.bx>
  8.    0x133d7b <__pthread_create_2_1+11>:    add $0x10279,%ebx
  9.    0x133d81 <__pthread_create_2_1+17>:    sub $0x4c,%esp
  10.    0x133d84 <__pthread_create_2_1+20>:    mov 0xc(%ebp),%edx
  11.    0x133d87 <__pthread_create_2_1+23>:    test %edx,%edx
    这是第一次。第二次就比较简单了,因为GOT里面有一个条目已经有了pthread_create函数的地址。

    
    本文里面两个PLT图来自http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/。这个博客内容相当的好,我学到了很多的东西。
参考文献:
 2 How to write share library.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态链接库中函数的地址确定---PLT和GOT 的相关文章

  • LaTex 使用plt.savefig保存矢量图并插入论文中

    问题描述 今天开始给实验结果画图了 xff0c 总觉得使用png格式的图片糊糊的 xff0c 于是决定研究一下如何将矢量图插入Latex中 解决方案 由于我需要插入的图片是使用python绘制的并通过plt savefig保存下来 通过参考
  • python plt.plot bar 设置绘图尺寸大小

    plt span class token punctuation span rcParams span class token punctuation span span class token string 39 figure figsi
  • 【问题】使用opencv读取并处理图片后用plt显示图像颜色的偏色问题处理

    1 问题 x1f631 x1f631 x1f631 使用opencv读取并处理图片后用plt显示图像颜色偏色问题 xff0c 比如 xff0c 原始图像为黄色调 xff0c 结果显示为蓝色调 或者 xff0c 原始图像为蓝色调 xff0c
  • plt.subplots_adjust(wspace=0.01, hspace=0.01)

    有时候这个质量调节没有变化 xff0c 依然保留大的gaps无法remove xff0c 这个时候试着调整一下figsize参数 xff0c 将figsize调小一点
  • Python:plt.imshow() 没反应 不显示图像

    问题描述 xff1a 调用plt imshow 函数之后 xff0c 程序没有报错 xff0c 但是并没有弹出窗口 xff0c 以显示图片 span class token keyword import span matplotlib sp
  • 用GDB跟踪观察共享库函数的地址翻译过程

    用GDB跟踪观察共享库函数的地址翻译过程 用GDB观察共享库函数的翻译过程 研究了一下共享库函数是怎样加载到当前进程中的 开始共享库函数地址放在GOT中 第一次调用时 ld将其翻译成函数在程序空间的真实地址 用GDB跟踪了一下整个过程 记录
  • Linux动态库(一)之同名符号

    万事皆有缘由 还是先从我遇到的这个问题说起 问 有一个主执行程序main 其中实现了函数foo 同时调用动态库liba so中的函数bar 而动态库liba so中也实现了foo 函数 那么在执行的时候如果在bar 中调用foo 会调用到哪
  • Linux System Calls Hooking Method Summary LD_PRELOAD

    Linux System Calls Hooking Method Summary 相关学习资料 http xiaonieblog com post 121 http hbprotoss github io posts li yong ld
  • Python3.5 中plt无法画出图像

    第一 sudo apt get install tk dev 正在读取状态信息 完成 将会同时安装下列软件 libfontconfig1 dev libfreetype6 dev libice dev libpng12 dev libpth
  • Linux中ELF格式文件介绍

    ELF Executable and Linkable Format 即可执行连接文件格式 是一种比较复杂的文件格式 但其应用广泛 与linux下的其他可执行文件 a out cof 相比 它对节的定义和gnu工具链对它的支持使它十分灵活
  • testdbg-测试调试器

    http baidutech blog 51cto com 4114344 743464 testdbg 测试调试器 2011 02 24 14 07 00 标签 测试 休闲 调试器 职场 testdbg 原创作品 允许转载 转载时请务必以
  • https://code.google.com/p/baiduhook/

    https code google com p baiduhook
  • dl_iterate_phdr

    http www helplib net s linux die 65 1099 man 3 dl iterate phdr shtml http linux die net man 3 dl iterate phdr dl iterate
  • Linux 平台一种进程代码注入方法

    Linux 平台一种进程代码注入方法 Posted on 2012年06月7日 用于在目标程序的 main 函数执行前完成一些操作 特定情况下用来调试还是不错的 源代码 fakemain c Heiher
  • Playing with ptrace, Part II

    Playing with ptrace Part II From Issue 104 December 2002 Dec 01 2002 By Pradeep Padala in SysAdmin In Part II of his ser
  • 在Linux程序中输出函数调用栈

    在Linux程序中输出函数调用栈 12 23 2013 程序发生异常时 将函数的调用栈打印出来 可以大大提高定位效率 Linux中提供了三个函数用来获取调用栈 1 2 3 4 5 6
  • python云图

    安装相关插件 python3 m pip install jieba wordcloud matplotlib import matplotlib pyplot as plt import jieba from wordcloud impo
  • linux hook

    http www codeproject com Articles 33340 Code Injection into Running Linux Application
  • 加密so文件中指定的函数

    加密so文件中指定的函数 作者 0n1y3nd丶 分类 逆向学习 发布时间 2014 09 04 22 24 61条评论 前言 上一篇文章中详细分析了对so文件中自定义section的加密 这一篇来分析下对so文件中自定义函数的加密 原文地
  • 一般函数指针和类的成员函数指针

    一般函数指针和类的成员函数指针 转载请注明原文网址 http www cnblogs com xianyunhe archive 2011 11 26 2264709 html 函数指针是通过指向函数的指针间接调用函数 函数指针可以实现对参

随机推荐

  • 调用微信内置 wx.config 配置问题

    var link location href ajax url WxJSSDK WxJS SDK aspx GetInfoMation 后台给你提供的接口 type Post data url link async false conten
  • [Spring Boot]04 使用IDEA快速搭建多模块项目

    目录 一 项目介绍 二 创建父工程 三 搭建多模块 1 搭建shopping api 2 搭建shopping bi 3 搭建shopping common 4 删除不需要的文件 5 多模块配置 1 父工程pom xml配置 2 子模块po
  • 打印回型数组-回型矩阵-环形数组

    刚才看到打印回形矩阵 或者回型数组 环形数组 网上一些方法感觉写的挺麻烦 还是自己写一遍吧 不妥之处还请各位看官不吝赐教 题目 输入一个整数N 打印出从1 N N的N N矩阵 比如N 3 构成矩阵 1 2 3 8 9 4 7 6 5 N 5
  • 分享:Go语言使用字符串的几个技巧

    本文小编将给出一些Go语言在处理字符串方面的技巧 对大家学习Go语言具有一定的参考借鉴价值 下面一起看看吧 一 字符串底层就是一个字节数组 这真的非常重要 而且影响着下面的其他几个技巧 当你创建一个字符串时 其本质就是一个字节的数组 这意味
  • Nginx代理连接Redis失败

    遇到了一个客户端连接Redis总是失败的问题 由于是通过nginx代理连接的 又尝试不通过nginx代理连接直接连接redis地址 不过连接很不稳定 不时就断了 因为这部分配置跑了一年多了 也没想到是nginx的问题 各种排查网络情况 弄了
  • xampp+Testlink安装问题

    安装xampp 一1 首先下载一个 xampp安装文件 记得分好32位还是64位 下载完后 点击安装 在出现选择安装路径的一个窗口 安装在C xampp 然后 直接Next一直到finsh 启动后效果为下图 如果启动成功了 那两个start
  • 前端框架Bootstrap

    bootstrap框架 内部提供了很多漂亮的标签样式和功能 我们只需要CV使用即可 bootstrap版本 推荐使用v3版本 Bootstrap v3 中文文档 Bootstrap 是最受欢迎的 HTML CSS 和 JavaScript
  • 前端根据token控制路由跳转(配置路由拦截全局前置守卫)

    在配置路由中需要拦截的加上 meta requiresAuth true import Vue from vue import VueRouter from vue router Vue use VueRouter const routes
  • qemu: 设备后端模拟

    目录 1 网卡模拟 2 网卡参数解析 3 qemu前端虚拟网卡设备创建 4 报文发送流程 5 报文发送流程 1 网卡模拟 参数 netdev type tap id eth0 ifname tap30 script no downscrip
  • NMOS/PMOS原理基础(祥:应该有点问题)

    1 NMOS PMOS原理图 2 导通性 P沟道MOSFET S极电压高于G极电压 P沟道MOSFET G极电压高于S极电压 3 NMOS PMOS一般用于开关电路 NMOS一般用于控制对电源端导通 PMOS一般用于控制对地端导通 4 常用
  • 首次运行 IntelliJ IDEA旗舰版

    首次运行IntelliJ IDEA需要执行以下任务 从以前的版本导入IntelliJ IDEA的设置 选择启动的IntelliJ IDEA是试用或激活许可证 接受许可协议 选择用户界面的主题 禁用不必要的插件 下载和安装额外的插件 从以前的
  • 微信小程序 通过获取地理位置查看天气

    1 在app json中写入 permission scope userLocation desc 你的位置信息将用于天气预报定位 2 申请和风天气APIKEY 和风天气开发平台 高效强大的天气API 天气SDK和天气插件 3 在js文件中
  • 图解通信原理与案例分析-28:四大全球卫星导航系统GNSS的基本原理与技术对比---中国的北斗、美国的GPS、欧洲的伽利略、俄罗斯的格洛纳斯

    前言 卫星导航是卫星通信的一个重要的分支 它是利用导航卫星通信进行测时 时间 和测距 定位 的广义的卫星通信系统 本文将介绍全球卫星导航系统GNSS的基本原理 以及对全球现有的4大导航卫星系统进行全方位的比较 关于卫星通信的基本知识 请参看
  • FLOPS和参数量比较小的模型,推理时间反而较长?

    两个模型 A 和 B A 模型的 FLOPS 和参数量均比 B 模型少一半 但 B 模型的推理速度却稍微比 A 模型快一些 出现这种情况由几种情况出现 一 运行平台的不同 这个很明显 在大多数情况下 GPU 平台下运行比 CPU快 二 在同
  • angular:获取组件自身html对象

    constructor private elt ElementRef
  • 系统设计.秒杀系统

    秒杀 秒杀是以压倒性优势一招致命或在极短时间 比如一秒钟 内解决对手 或者称瞬秒 瞬间秒杀 该词最初来自网络游戏 形容一瞬间杀死一个游戏角色之快 电商系统中的秒杀是指 短时间内抢够商品的场景 这是一个营销策略 通常销售时间区间较短 价格稍低
  • 硅谷裁员10万人,一个时代结束了!

    见字如面 我是军哥 2022年7月 微软宣布裁员计划 裁员规模不超过18万员工总数的1 并于10月18日 试裁 1千人左右 11月10日 Meta的创始人兼CEO扎克伯格发布全员信 确认公司将裁员逾11000人 这是这家科技巨头18年来历史
  • 李雅普诺夫函数设计

    一 线性时不变系统 1 1 原理 对于线性时不变系统 x A
  • 一天内时针和分针重叠的次数

    一天内时针和分针重叠的次数 这是一道谷歌面试题 答案是22次 分别是上午 12 00 1 05 2 11 3 16 4 22 5 27 6 33 7 38 8 44 9 49 10 55 下午12 00 1 05 2 11 3 16 4 2
  • 动态链接库中函数的地址确定---PLT和GOT

    动态链接库中函数的地址确定 PLT和GOT 2012 09 16 20 27 42 分类 C C 前面写过动态链接库 延迟绑定的一篇博文 那篇文章我非常喜欢 但是当时刚搞清楚 自己写的比较凌乱 我最近学习了Ulrich Drepper的Ho