ldd和nm是Linux下两个非常实用的程序分析工具。ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具,objdump用来查看源代码与汇编代码,-d只查看汇编代码,-S查看c和汇编代码。

    #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> int global = ; int main(int argc, char **argv)
{
pid_t pid;
int stack = ;
int *heap; heap = (int*)malloc(sizeof(int));
*heap = ; pid = fork();
if(pid < ){
perror("fail to fork");
exit(-);
}else{
if( == pid){
global++;
stack++;
(*heap)++; printf("In sub-process, global: %d, stack: %d, heap: %d\n", global, stack, *heap);
exit();
}else{
sleep();
printf("In parent-process, global: %d, stack: %d, heap: %d\n", global, stack, *heap);
}
} return ;
}

源代码如上边所示,偷懒,直接使用了别人的代码。

1、使用命令:gcc -g tooltest.c -o tooltest 编译源码生成可执行文件tooltest

2、使用命令:ldd tooltest 其中ldd工具用来分析程序运行时需要依赖的动态链接库

3、使用命令:nm tooltest 其中nm工具用来查看指定程序中的符号表信息

4、使用命令:objdump -S tooltest 其中objdump工具用来查看C源代码与汇编代码

补充如下:

1、ldd

格式:ldd [options] file   

功能:列出file运行所需的共享库

参数:

-d    执行重定位并报告所有丢失的函数

-r    执行对函数和对象的重定位并报告丢失的任何函数或对象

 munication  ~  ldd tooltest
linux-gate.so. (0xb77c5000)
libc.so. => /usr/lib/libc.so. (0xb75b2000)
/lib/ld-linux.so. (0xb77c7000)

上边是ldd的输出结果,将其分为3列来看:

■ 第一列:程序需要依赖什么库

■ 第二列:系统提供的与程序需要的库对应的库名称

■ 第三列:依赖库加载的开始地址

通过上面的这些信息,我们可以总结出下面的用途:

(1) 通过对比第一列和第二列,我们可以知道程序需要的动态链接库和系统实际提供的是否相比配。

(2) 通过第三列,我们可以知道当前动态链接库中的符号在进程地址空间中的起始位置。

2、nm

格式:nm [options] file

功能:列出file中的所有符号

参数:

-C   将符号转化为用户级的名字

-s   当用于.a文件即静态库时,输出把符号名映射到定义该符号的模块或成员名的索引

-u   显示在file外定义的符号或没有定义的符号

-l   显示每个符号的行号,或为定义符号的重定义项

  munication  ~  nm tooltest
B __bss_start
b completed.
w __cxa_finalize@@GLIBC_2.1.3
D __data_start
W data_start
t deregister_tm_clones
000005d0 t __do_global_dtors_aux
00001ef8 t __do_global_dtors_aux_fini_array_entry
0000202c D __dso_handle
00001efc d _DYNAMIC
D _edata
B _end
U exit@@GLIBC_2.
T _fini
U fork@@GLIBC_2.
0000079c R _fp_hw
t frame_dummy
00001ef4 t __frame_dummy_init_array_entry
r __FRAME_END__
D global
d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000081c r __GNU_EH_FRAME_HDR
T _init
00001ef8 t __init_array_end
00001ef4 t __init_array_start
000007a0 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
T __libc_csu_fini
T __libc_csu_init
U __libc_start_main@@GLIBC_2.
0000062d T main
U malloc@@GLIBC_2.
U perror@@GLIBC_2.
U printf@@GLIBC_2.
t register_tm_clones
U sleep@@GLIBC_2.
000004f0 T _start
D __TMC_END__
T __x86.get_pc_thunk.bx
T __x86.get_pc_thunk.dx
T __x86.get_pc_thunk.si

上面便是tooltest这个程序中所有的符号,首先介绍一下上面输出内容的格式:

■ 第一列:当前符号的地址。

■ 第二列:当前符号的类型(关于类型的说明,可以查看手册页man nm详细阅读)。

■ 第三列:当前符号的名称。

使用nm主要有一下几个方面的帮助:

(1) 判断指定的程序中有没有指定的符号,比较常用的方式为:nm –C program | grep symbol

(2) 解决程序编译时undefined reference的错误,以及multiple definition的错误。

(3) 查看某个符号的地址,以及在进程空间的大概位置(.bss, .data, .text段,具体可以通过第二列的类型来判断)。

显示结果的符号如下:

部分符号类型说明

A : 该符号的值是绝对的,在以后的链接过程中,不允许进行改变。这样的符号值,常常出现在中断向量表中,例如用符号来表示各个中断向量函数在中断向量表中的位置。

B : 该符号的值出现在非初始化数据段(.bss)中。例如,在一个文件中定义全局static int test。则该符号test的类型为b,位于bss section中。其值表示该符号在bss段中的偏移。一般而言,bss段分配于RAM中 。

C : 该符号为common。common symbol是未初始话数据段。该符号没有包含于一个普通section中。只有在链接过程中才进行分配。符号的值表示该符号需要的字节数。例如在一个c文件中,定义int test,并且该符号在别的地方会被引用,则该符号类型即为C。否则其类型为B。

D : 该符号位于初始化数据段中。一般来说,分配到.data section中。例如定义全局int baud_table[5] = {9600, 19200, 38400, 57600, 115200},则会分配于初始化数据段中。

G : 该符号也位于初始化数据段中。主要用于small object提高访问small data object的一种方式。

I : 该符号是对另一个符号的间接引用。

N : 该符号是一个debugging符号。

R : 该符号位于只读数据段。例如定义全局const int test[] = {123, 123};则test就是一个只读数据区的符号。注意在cygwin下如果使用gcc直接编译成MZ格式时,源文件中的test对应_test,并且其符号类型为D,即初始化数据段中。但是如果使用m6812-elf-gcc这样的交叉编译工具,源文件中的test对应目标文件的test,即没有添加下划线,并且其符号类型为R。一般而言,位于rodata section。值得注意的是,如果在一个函数中定义const char *test = “abc”, const char test_int = 3。使用nm都不会得到符号信息,但是字符串“abc”分配于只读存储器中,test在rodata section中,大小为4。

S : 符号位于非初始化数据段,用于small object。

T : 该符号位于代码段text section。

U : 该符号在当前文件中是未定义的,即该符号的定义在别的文件中。例如,当前文件调用另一个文件中定义的函数,在这个被调用的函数在当前就是未定义的;但是在定义它的文件中类型是T。但是对于全局变量来说,在定义它的文件中,其符号类型为C,在使用它的文件中,其类型为U。

V : 该符号是一个weak object。

W : The symbol is a weak symbol that has not been specifically tagged as a weak object symbol.

- : 该符号是a.out格式文件中的stabs symbol。

? : 该符号类型没有定义。

3、objdump

格式:objdump [options] file   

功能:列出file运行所需的共享库

参数:

-s    只是显示汇编源码

-S    同时显示汇编和C语言代码

 munication  ~  objdump -S tooltest

 tooltest:     文件格式 elf32-i386

 Disassembly of section .init:

  <_init>:
: push %ebx
: ec sub $0x8,%esp
: e8 f7 call <__x86.get_pc_thunk.bx>
: c3 c7 1b add $0x1bc7,%ebx
43f: 8b f4 ff ff ff mov -0xc(%ebx),%eax
: c0 test %eax,%eax
: je 44e <_init+0x1e>
: e8 9a call 4e8 <.plt.got+0x8>
44e: c4 add $0x8,%esp
: 5b pop %ebx
: c3 ret Disassembly of section .plt: <.plt>:
: ff b3 pushl 0x4(%ebx)
: ff a3 jmp *0x8(%ebx)
46c: add %al,(%eax)
... <printf@plt>:
: ff a3 0c jmp *0xc(%ebx)
: push $0x0
47b: e9 e0 ff ff ff jmp <.plt> <sleep@plt>:
: ff a3 jmp *0x10(%ebx)
: push $0x8
48b: e9 d0 ff ff ff jmp <.plt> <perror@plt>:
: ff a3 jmp *0x14(%ebx)
: push $0x10
49b: e9 c0 ff ff ff jmp <.plt> 000004a0 <malloc@plt>:
4a0: ff a3 jmp *0x18(%ebx)
4a6: push $0x18
4ab: e9 b0 ff ff ff jmp <.plt> 000004b0 <exit@plt>:
4b0: ff a3 1c jmp *0x1c(%ebx)
4b6: push $0x20
4bb: e9 a0 ff ff ff jmp <.plt> 000004c0 <__libc_start_main@plt>:
4c0: ff a3 jmp *0x20(%ebx)
4c6: push $0x28
4cb: e9 ff ff ff jmp <.plt> 000004d0 <fork@plt>:
4d0: ff a3 jmp *0x24(%ebx)
4d6: push $0x30
4db: e9 ff ff ff jmp <.plt> Disassembly of section .plt.got: 000004e0 <.plt.got>:
4e0: ff a3 f0 ff ff ff jmp *-0x10(%ebx)
4e6: xchg %ax,%ax
4e8: ff a3 f4 ff ff ff jmp *-0xc(%ebx)
4ee: xchg %ax,%ax Disassembly of section .text: 000004f0 <_start>:
4f0: ed xor %ebp,%ebp
4f2: 5e pop %esi
4f3: e1 mov %esp,%ecx
4f5: e4 f0 and $0xfffffff0,%esp
4f8: push %eax
4f9: push %esp
4fa: push %edx
4fb: e8 call <_start+0x32>
: c3 1b add $0x1b00,%ebx
: 8d e7 ff ff lea -0x1880(%ebx),%eax
50c: push %eax
50d: 8d e7 ff ff lea -0x18e0(%ebx),%eax
: push %eax
: push %ecx
: push %esi
: ff b3 f8 ff ff ff pushl -0x8(%ebx)
51c: e8 9f ff ff ff call 4c0 <__libc_start_main@plt>
: f4 hlt
: 8b 1c mov (%esp),%ebx
: c3 ret
: xchg %ax,%ax
: xchg %ax,%ax
52a: xchg %ax,%ax
52c: xchg %ax,%ax
52e: xchg %ax,%ax <__x86.get_pc_thunk.bx>:
: 8b 1c mov (%esp),%ebx
: c3 ret
: xchg %ax,%ax
: xchg %ax,%ax
: xchg %ax,%ax
53a: xchg %ax,%ax
53c: xchg %ax,%ax
53e: xchg %ax,%ax <deregister_tm_clones>:
: e8 e4 call <__x86.get_pc_thunk.dx>
: c2 bb 1a add $0x1abb,%edx
54b: 8d 8a lea 0x34(%edx),%ecx
: 8d lea 0x34(%edx),%eax
: c8 cmp %ecx,%eax
: 1d je <deregister_tm_clones+0x38>
55b: 8b ec ff ff ff mov -0x14(%edx),%eax
: c0 test %eax,%eax
: je <deregister_tm_clones+0x38>
: push %ebp
: e5 mov %esp,%ebp
: ec sub $0x14,%esp
56b: push %ecx
56c: ff d0 call *%eax
56e: c4 add $0x10,%esp
: c9 leave
: c3 ret
: nop
: 8d lea 0x0(%esi,%eiz,),%esi
: f3 c3 repz ret
57a: 8d b6 lea 0x0(%esi),%esi <register_tm_clones>:
: e8 a4 call <__x86.get_pc_thunk.dx>
: c2 7b 1a add $0x1a7b,%edx
58b: push %ebp
58c: 8d 8a lea 0x34(%edx),%ecx
: 8d lea 0x34(%edx),%eax
: c8 sub %ecx,%eax
59a: e5 mov %esp,%ebp
59c: push %ebx
59d: c1 f8 sar $0x2,%eax
5a0: c3 mov %eax,%ebx
5a2: ec sub $0x4,%esp
5a5: c1 eb 1f shr $0x1f,%ebx
5a8: d8 add %ebx,%eax
5aa: d1 f8 sar %eax
5ac: je 5c2 <register_tm_clones+0x42>
5ae: 8b fc ff ff ff mov -0x4(%edx),%edx
5b4: d2 test %edx,%edx
5b6: 0a je 5c2 <register_tm_clones+0x42>
5b8: ec sub $0x8,%esp
5bb: push %eax
5bc: push %ecx
5bd: ff d2 call *%edx
5bf: c4 add $0x10,%esp
5c2: 8b 5d fc mov -0x4(%ebp),%ebx
5c5: c9 leave
5c6: c3 ret
5c7: f6 mov %esi,%esi
5c9: 8d bc lea 0x0(%edi,%eiz,),%edi 000005d0 <__do_global_dtors_aux>:
5d0: push %ebp
5d1: e5 mov %esp,%ebp
5d3: push %ebx
5d4: e8 ff ff ff call <__x86.get_pc_thunk.bx>
5d9: c3 1a add $0x1a27,%ebx
5df: ec sub $0x4,%esp
5e2: bb cmpb $0x0,0x34(%ebx)
5e9: jne <__do_global_dtors_aux+0x42>
5eb: 8b f0 ff ff ff mov -0x10(%ebx),%eax
5f1: c0 test %eax,%eax
5f3: je <__do_global_dtors_aux+0x36>
5f5: ec 0c sub $0xc,%esp
5f8: ff b3 2c pushl 0x2c(%ebx)
5fe: e8 dd fe ff ff call 4e0 <.plt.got>
: c4 add $0x10,%esp
: e8 ff ff ff call <deregister_tm_clones>
60b: c6 movb $0x1,0x34(%ebx)
: 8b 5d fc mov -0x4(%ebp),%ebx
: c9 leave
: c3 ret
: f6 mov %esi,%esi
: 8d bc lea 0x0(%edi,%eiz,),%edi <frame_dummy>:
: push %ebp
: e5 mov %esp,%ebp
: 5d pop %ebp
: e9 ff ff ff jmp <register_tm_clones> <__x86.get_pc_thunk.dx>:
: 8b mov (%esp),%edx
62c: c3 ret 0000062d <main>:
#include <unistd.h> int global = ; int main(int argc, char **argv)
{
62d: 8d 4c lea 0x4(%esp),%ecx
: e4 f0 and $0xfffffff0,%esp
: ff fc pushl -0x4(%ecx)
: push %ebp
: e5 mov %esp,%ebp
63a: push %ebx
63b: push %ecx
63c: ec sub $0x10,%esp
63f: e8 ec fe ff ff call <__x86.get_pc_thunk.bx>
: c3 bc add $0x19bc,%ebx
pid_t pid;
int stack = ;
64a: c7 ec movl $0x1,-0x14(%ebp)
int *heap; heap = (int*)malloc(sizeof(int));
: ec 0c sub $0xc,%esp
: 6a push $0x4
: e8 fe ff ff call 4a0 <malloc@plt>
65b: c4 add $0x10,%esp
65e: f0 mov %eax,-0x10(%ebp)
*heap = ;
: 8b f0 mov -0x10(%ebp),%eax
: c7 movl $0x2,(%eax) pid = fork();
66a: e8 fe ff ff call 4d0 <fork@plt>
66f: f4 mov %eax,-0xc(%ebp)
if(pid < ){
: 7d f4 cmpl $0x0,-0xc(%ebp)
: 1c jns <main+0x67>
perror("fail to fork");
: ec 0c sub $0xc,%esp
67b: 8d a4 e7 ff ff lea -0x185c(%ebx),%eax
: push %eax
: e8 fe ff ff call <perror@plt>
: c4 add $0x10,%esp
exit(-);
68a: ec 0c sub $0xc,%esp
68d: 6a ff push $0xffffffff
68f: e8 1c fe ff ff call 4b0 <exit@plt>
}else{
if( == pid){
: 7d f4 cmpl $0x0,-0xc(%ebp)
: jne 6e3 <main+0xb6>
global++;
69a: 8b mov 0x30(%ebx),%eax
6a0: c0 add $0x1,%eax
6a3: mov %eax,0x30(%ebx)
stack++;
6a9: ec addl $0x1,-0x14(%ebp)
(*heap)++;
6ad: 8b f0 mov -0x10(%ebp),%eax
6b0: 8b mov (%eax),%eax
6b2: 8d lea 0x1(%eax),%edx
6b5: 8b f0 mov -0x10(%ebp),%eax
6b8: mov %edx,(%eax) printf("In sub-process, global: %d, stack: %d, heap: %d\n", global, stack, *heap);
6ba: 8b f0 mov -0x10(%ebp),%eax
6bd: 8b mov (%eax),%edx
6bf: 8b mov 0x30(%ebx),%eax
6c5: push %edx
6c6: ff ec pushl -0x14(%ebp)
6c9: push %eax
6ca: 8d b4 e7 ff ff lea -0x184c(%ebx),%eax
6d0: push %eax
6d1: e8 9a fd ff ff call <printf@plt>
6d6: c4 add $0x10,%esp
exit();
6d9: ec 0c sub $0xc,%esp
6dc: 6a push $0x0
6de: e8 cd fd ff ff call 4b0 <exit@plt>
}else{
sleep();
6e3: ec 0c sub $0xc,%esp
6e6: 6a push $0x2
6e8: e8 fd ff ff call <sleep@plt>
6ed: c4 add $0x10,%esp
printf("In parent-process, global: %d, stack: %d, heap: %d\n", global, stack, *heap);
6f0: 8b f0 mov -0x10(%ebp),%eax
6f3: 8b mov (%eax),%edx
6f5: 8b mov 0x30(%ebx),%eax
6fb: push %edx
6fc: ff ec pushl -0x14(%ebp)
6ff: push %eax
: 8d e8 e7 ff ff lea -0x1818(%ebx),%eax
: push %eax
: e8 fd ff ff call <printf@plt>
70c: c4 add $0x10,%esp
}
} return ;
70f: b8 mov $0x0,%eax
}
: 8d f8 lea -0x8(%ebp),%esp
: pop %ecx
: 5b pop %ebx
: 5d pop %ebp
71a: 8d fc lea -0x4(%ecx),%esp
71d: c3 ret
71e: xchg %ax,%ax <__libc_csu_init>:
: push %ebp
: push %edi
: push %esi
: push %ebx
: e8 call <__x86.get_pc_thunk.si>
: c6 d7 add $0x18d7,%esi
72f: ec 0c sub $0xc,%esp
: 8b 6c mov 0x28(%esp),%ebp
: 8d 9e f8 fe ff ff lea -0x108(%esi),%ebx
73c: e8 ee fc ff ff addr16 call <_init>
: 8d f4 fe ff ff lea -0x10c(%esi),%eax
: c3 sub %eax,%ebx
74a: c1 fb sar $0x2,%ebx
74d: db test %ebx,%ebx
74f: je <__libc_csu_init+0x55>
: ff xor %edi,%edi
: nop
: 8d lea 0x0(%esi,%eiz,),%esi
: ec sub $0x4,%esp
75b: push %ebp
75c: ff 2c pushl 0x2c(%esp)
: ff 2c pushl 0x2c(%esp)
: ff be f4 fe ff ff call *-0x10c(%esi,%edi,)
76b: c7 add $0x1,%edi
76e: c4 add $0x10,%esp
: fb cmp %edi,%ebx
: e3 jne <__libc_csu_init+0x38>
: c4 0c add $0xc,%esp
: 5b pop %ebx
: 5e pop %esi
77a: 5f pop %edi
77b: 5d pop %ebp
77c: c3 ret
77d: 8d lea 0x0(%esi),%esi <__libc_csu_fini>:
: f3 c3 repz ret <__x86.get_pc_thunk.si>:
: 8b mov (%esp),%esi
: c3 ret Disassembly of section .fini: <_fini>:
: push %ebx
: ec sub $0x8,%esp
78c: e8 9f fd ff ff call <__x86.get_pc_thunk.bx>
: c3 6f add $0x186f,%ebx
: c4 add $0x8,%esp
79a: 5b pop %ebx
79b: c3 ret

都见到源代码了,想怎么折腾都可以,尽情发挥吧

4、splint

格式:splint [options] file.c   

功能:列出file.c代码的缺陷

 1 [guochaoxxl@opensource chapter01]$ splint p5_01.c
2 Splint 3.1.2 --- 23 Apr 2014
3
4 p5_01.c: (in function main)
5 p5_01.c:11:17: Variable num used before definition
6 An rvalue is used that may not be initialized to a value on some execution
7 path. (Use -usedef to inhibit warning)
8 p5_01.c:12:17: Value *ptrNum used before definition
9 p5_01.c:3:14: Parameter argc not used
10 A function parameter is not used in the body of the function. If the argument
11 is needed for type compatibility or future plans, use /*@unused@*/ in the
12 argument declaration. (Use -paramuse to inhibit warning)
13 p5_01.c:3:27: Parameter argv not used
14
15 Finished checking --- 4 code warnings

  容易看出有4个代码警告,也可以在代码编辑时使用-Wall选项来完成同样的工作。

linux程序分析工具的更多相关文章

  1. Linux程序分析工具:ldd和nm

    ldd和nm是Linux下两个非常实用的程序分析工具.其中,ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具. 1 ldd 格式:ldd [option ...

  2. linux程序分析工具介绍(一)—-”/proc”

    写在最前面:在开始本文之前,笔者认为先有必要介绍一下linux下的man,如果读者手头用linux系统,直接在终端输入man man便可以看到详细的说明,我在这里简单的总结一下,man命令是用来查看l ...

  3. Linux程序分析工具介绍—ldd,nm

    原文链接:http://blog.csdn.net/statdm/article/details/7759100 本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具.ldd是用来分析 ...

  4. linux程序分析工具介绍(三)——sar

    本文要介绍的sar,是linux下用来分析系统本身运行情况的非常有用的工具.我们知道,程序在操作系统上要运行,要关注的点不外乎内存,CPU和IO(包括磁盘IO和网络IO).我们的应用程序在操作系统中运 ...

  5. linux程序分析工具介绍(二)—-ldd,nm

    本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具.ldd是用来分析程序运行时需要依赖的动态库的工具:nm是用来查看指定程序中的符号表相关内容的工具.下面通过例子,分别来介绍一下这两 ...

  6. Linux资源分析工具杂谈(长文慎入)

    Linux资源分析工具杂谈 开篇之前请大家先思考一个问题:        磁盘的平均I/O响应时间是1 ms,这个指标是好,还是差? 众所周知,计算机科学是客观的,也就是说对于一个给定的问题,我们总是 ...

  7. (转)超全整理!Linux性能分析工具汇总合集

    超全整理!Linux性能分析工具汇总合集 原文:http://rdc.hundsun.com/portal/article/731.html 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望, ...

  8. Linux 日志分析工具(logwatch)安装及使用

    Linux 日志分析工具(logwatch)安装及使用 日志是非常重要的系统文件,管理员每天的重要工作就是分析和查看服务器的日志,判断服务器的健康状态.但是日志管理又是一项非常枯燥的工作,如果需要管理 ...

  9. Linux性能分析工具的安装和使用

    转自:http://blog.chinaunix.net/uid-26488891-id-3118279.html Normal 0 7.8 磅 0 2 false false false EN-US ...

随机推荐

  1. ZOJ 3605Find the Marble(dp)

    ZOJ 3605 大体意思就是 找出随机选了K个交换后 石子在第i个罐子里的概率最大 也就是可能的总数最大 这样就可以写出递推方程 dp[i][j][k] += dp[i-1][e][k]; (0&l ...

  2. C#菜鸟正则表达式一

    LZ菜鸟,仅整理笔记,顺带记录一下,谓之增加印象. LZ认为,没必要太纠结原理,模型, 屌丝能用就对了,剩下的事情用多了自然会去探索. 中文:正则表达式,英文:Regular  ExPression, ...

  3. OpenGl之旅-—如何使用code blocks创建一个opengl项目

    开始学习opengl啦,练习用的编辑器是code blocks. 首先当然是要清楚如何使用code blocks创建一个opengl项目了. 首先必须先引用opengl的库glut,网上百度下载一个完 ...

  4. Java对Redis基本使用

    1 引入jar包 java是通过Jedis对redis进行操作的,首先引入jedis.jar <dependency> <groupId>redis.clients</g ...

  5. js面向对象之构造函数

    最简单的面向对象程序<script type="text/javascript"> var obj = new Object(); obj.qq = '10791611 ...

  6. hibernate4+spring4+struts2的Maven中的pom.xml文件的配置

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  7. Swift protocol extension method is called instead of method implemented in subclass

    Swift protocol extension method is called instead of method implemented in subclass protocol MyProto ...

  8. spring cloud 概念

    微服务构架需要使用场景: 1.可以将一个系统拆分成几个系统. 2.每个子系统可以部署多个应用,多个应用之间可以使用负载均衡. 3.需要一个服务注册中心,所有的服务都在一个注册中心注册,负载均衡也是通过 ...

  9. SpringBoot 快速开发框架

    学习资源:https://ke.qq.com/course/260513(这是Springboot升级版本教程,里面还有一个初级版本的) 1.第一个测试程序,那个覆盖方法加上@Override会报错, ...

  10. sysbench下载安装

    涉及到sysbench源码的配置和编译,首先确认系统安装了gcc gcc-c++编译器:确认安装了autoconf .automake.libtool等:[root@PC download]# rpm ...