0


【Linux】程序员的基本素养学习

这是目录

写在前面

本文记录自己的学习生涯,学一点记一点,做好准备随时能够提桶。

一、内存管理

1、分段

程序所需要的内存空间大小的虚拟空间映射到某个物理地址空间。
问题:无法高效的使用整个内存,容易造成内存的浪费(为程序分配物理内存,程序并未完全使用物理内存)。

2、分页

分页:1、为了解决分段所带来的问题,即内存的高效使用;1、保护作用,可以单独设置每个页的属性、权限。
将内存分成一个个固定大小的页,如1K or 4K(由硬件决定),在此基础上,可以将程序的内存进一步细分。将程序使用的部分内存分配到物理内存,对于暂未使用的部分内存先不分配实际物理内存,后续使用到后再分配实际的物理地址。
进程当前正在使用的VP0、VP1分配到物理地址PP2、PP0,另一部分VP3、VP2分配到磁盘上,还有暂未使用的VP4、VP6、VP7不进行分配。

在这里插入图片描述现在虚拟地址到物理地址的转换有专门的硬件完成(MMU):
在这里插入图片描述

二、线程管理

三、静态库

1、编译

在这里插入图片描述
a.c文件用于下列结果步骤演示
为了简化显示内容,文件尽可能的进行了精简。

#definePI(111)intmain(){if(PI);return0;}

1.1、预处理

gcc -E a.c -i a.i
pi@NanoPi-NEO2:~/project/test$ cat b.i
# 1"b.c"
# 1"<built-in>"
# 1"<command-line>"
# 31"<command-line>"
# 1"/usr/include/stdc-predef.h"134
# 32"<command-line>"2
# 1"b.c"intmain(){if((111));return0;}

展开宏,替换头文件,去掉注释,添加行号,保留编译命令–>xx.i

1.2、编译

gcc -S a.i -i a.s
pi@NanoPi-NEO2:~/project/test$ cat b.s 
        .arch armv8-a
        .file   "b.c".text
        .align  2.global main
        .type   main,%function
main:.LFB0:.cfi_startproc
        mov     w0,0
        ret
        .cfi_endproc
.LFE0:.size   main,.-main
        .ident  "GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0".section        .note.GNU-stack,"",@progbits

生成汇编文件–>xx.s

1.3、汇编

gcc -E a.c -i a.i

将汇编文件生成机器代码–>xx.o

1.4、链接

gcc -E a.c -i a.i

将文件之前的引用(函数变量)链接在一起。
在不同的文件中会生成一张符号表,表中明确指出了文件中的所有符号(函数和变量),方便其他文件引用。
–>xx.out

2、编译器

3、目标文件

.text

代码段

.data

已经初始化的非0数据段(全局变量,局部静态变量,已经分配空间占实际内存)

.bss

未初始化或初始化为0的数据段(未初始化可能默认为0,没有必要在这个阶段分配空间,因此为空不分配空间,只保留符号表)
在这里插入图片描述举个栗子:

#include"stdio.h"#include"stdint.h"uint16_t temp_1 =222;uint16_t temp_2;intmian(){staticuint16_t temp_3 =111;staticuint16_t temp_4;

    temp_1 = temp_3++;
    temp_2 = temp_1++;printf("this is test:%d\r\n",temp_1);return0;}

编译上文.c:

gcc -c main.c

使用objdump查看上述代码编译生成的.o文件的信息。

objdump -x -s -d main.o 

输出文件如下:

pi@NanoPi-NEO2:~/project/test$ objdump -x -s -d main.o 

main.o:     file format elf64-littleaarch64
main.o
architecture: aarch64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000private flags =0:

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0.text         0000008800000000000000000000000000000000000000402**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1.data         0000000400000000000000000000000000000000000000c8  2**1
                  CONTENTS, ALLOC, LOAD, DATA
  2.bss          0000000200000000000000000000000000000000000000cc  2**1
                  ALLOC
  3.rodata       0000001200000000000000000000000000000000000000d0  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4.comment      0000002b  00000000000000000000000000000000000000e22**0
                  CONTENTS, READONLY
  5.note.GNU-stack 00000000000000000000000000000000000000000000010d  2**0
                  CONTENTS, READONLY
  6.eh_frame     0000003800000000000000000000000000000000000001102**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
SYMBOL TABLE:0000000000000000 l    df *ABS*0000000000000000 main.c
0000000000000000 l    d  .text  0000000000000000.text
0000000000000000 l    d  .data  0000000000000000.data
0000000000000000 l    d  .bss   0000000000000000.bss
0000000000000000 l    d  .rodata        0000000000000000.rodata
0000000000000002 l     O .data  0000000000000002 temp_3.38380000000000000000 l     O .bss   0000000000000002 temp_4.38390000000000000000 l    d  .note.GNU-stack        0000000000000000.note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000.eh_frame
0000000000000000 l    d  .comment       0000000000000000.comment
0000000000000000 g     O .data  0000000000000002 temp_1
0000000000000002       O *COM*0000000000000002 temp_2
0000000000000000 g     F .text  0000000000000088 mian
0000000000000000*UND*0000000000000000 printf

Contents of section .text:0000 fd7bbfa9 fd030091 0000009000000091.{..............00100000407901040011223c0012 01000090..@y...."<......002021000091220000790100009021000091!..."..y....!...003020000079000000900000009100004079..y..........@y
 004001040011223c0012 0100009021000091...."<......!...00502200007901000090210040f9 20000079  "[email protected]
 0060000000900000009100004079 e103002a  ..........@y...*007000000090000000910000009400008052...............R
 0080 fd7bc1a8 c0035fd6                    .{...._.        
Contents of section .data:0000 de006f00                             ..o.            
Contents of section .rodata:00007468697320697320746573743a25640d  this is test:%d.00100a00                                 ..              
Contents of section .comment:0000004743433a202855 62756e747520392e  .GCC:(Ubuntu 9.0010332e302d 31377562756e7475317e32303.0-17ubuntu1~2000202e30342920392e332e3000.04)9.3.0.     
Contents of section .eh_frame:00001000000000000000017a5200 04781e01.........zR..x..00101b0c1f00 200000001800000000000000...............00208800000000410e109d029e01 60dedd0e  .....A......`...00300000000000000000........        

Disassembly of section .text:0000000000000000<mian>:0:   a9bf7bfd        stp     x29, x30,[sp, #-16]!4:910003fd        mov     x29, sp
   8:90000000        adrp    x0,0<mian>8: R_AARCH64_ADR_PREL_PG_HI21   .data+0x2
   c:91000000        add     x0, x0, #0x0
                        c: R_AARCH64_ADD_ABS_LO12_NC    .data+0x210:79400000        ldrh    w0,[x0]14:11000401        add     w1, w0, #0x118:12003c22        and     w2, w1, #0xffff1c:90000001        adrp    x1,0<mian>1c: R_AARCH64_ADR_PREL_PG_HI21  .data+0x220:91000021        add     x1, x1, #0x020: R_AARCH64_ADD_ABS_LO12_NC   .data+0x224:79000022        strh    w2,[x1]28:90000001        adrp    x1,0<mian>28: R_AARCH64_ADR_PREL_PG_HI21  temp_1
  2c:91000021        add     x1, x1, #0x02c: R_AARCH64_ADD_ABS_LO12_NC   temp_1
  30:79000020        strh    w0,[x1]34:90000000        adrp    x0,0<mian>34: R_AARCH64_ADR_PREL_PG_HI21  temp_1
  38:91000000        add     x0, x0, #0x038: R_AARCH64_ADD_ABS_LO12_NC   temp_1
  3c:79400000        ldrh    w0,[x0]40:11000401        add     w1, w0, #0x144:12003c22        and     w2, w1, #0xffff48:90000001        adrp    x1,0<mian>48: R_AARCH64_ADR_PREL_PG_HI21  temp_1
  4c:91000021        add     x1, x1, #0x04c: R_AARCH64_ADD_ABS_LO12_NC   temp_1
  50:79000022        strh    w2,[x1]54:90000001        adrp    x1,2<mian+0x2>54: R_AARCH64_ADR_GOT_PAGE      temp_2
  58:   f9400021        ldr     x1,[x1]58: R_AARCH64_LD64_GOT_LO12_NC  temp_2
  5c:79000020        strh    w0,[x1]60:90000000        adrp    x0,0<mian>60: R_AARCH64_ADR_PREL_PG_HI21  temp_1
  64:91000000        add     x0, x0, #0x064: R_AARCH64_ADD_ABS_LO12_NC   temp_1
  68:79400000        ldrh    w0,[x0]6c:2a0003e1        mov     w1, w0
  70:90000000        adrp    x0,0<mian>70: R_AARCH64_ADR_PREL_PG_HI21  .rodata
  74:91000000        add     x0, x0, #0x074: R_AARCH64_ADD_ABS_LO12_NC   .rodata
  78:94000000        bl      0<printf>78: R_AARCH64_CALL26    printf
  7c:52800000        mov     w0, #0x0// #080:   a8c17bfd        ldp     x29, x30,[sp], #1684:   d65f03c0        ret

.data段为初始化非0的数据,temp_1(de)和temp_3(6f)。而temp_2和temp_4并未分配空间,存放于bss。

attribute

**attribute((section(“dame”)))**,在函数或者变量前加上这个,表示将函数或者变量放置在name段内。如下,新增一个dame段

#include"stdio.h"#include"stdint.h"__attribute__((section(".demo")))uint8_t tttt;intmian(){printf("this is test\r\n");return0;}
pi@NanoPi-NEO2:~/project/test$ objdump -x -s -d main_1.o 

main_1.o:     file format elf64-littleaarch64
main_1.o
architecture: aarch64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000private flags =0:

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0.text         0000002000000000000000000000000000000000000000402**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1.data         0000000000000000000000000000000000000000000000602**0
                  CONTENTS, ALLOC, LOAD, DATA
  2.bss          0000000000000000000000000000000000000000000000602**0
                  ALLOC
  3.demo         0000000100000000000000000000000000000000000000602**0
                  CONTENTS, ALLOC, LOAD, DATA
  4.rodata       0000000e  00000000000000000000000000000000000000682**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5.comment      0000002b  00000000000000000000000000000000000000762**0
                  CONTENTS, READONLY
  6.note.GNU-stack 0000000000000000000000000000000000000000000000a1  2**0
                  CONTENTS, READONLY
  7.eh_frame     0000003800000000000000000000000000000000000000a8  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

3.1、符号

查看文件的符号表:
新建main_1.c文件

#include"stdio.h"#include"stdint.h"__attribute__((section(".demo")))uint8_t tttt;uint8_t temp_1 =0;uint8_t temp_2 =0;voidfun(uint8_t test){printf("this is test:%d\r\n",test);}intmian(){
    temp_1 = temp_2++;fun(temp_1);return0;}

编译并查看文件内容:

pi@NanoPi-NEO2:~/project/test$ readelf -s  main_1.o

Symbol table '.symtab' contains 21 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0:00000000000000000 NOTYPE  LOCAL  DEFAULT  UND 
     1:00000000000000000 FILE    LOCAL  DEFAULT  ABS main_1.c
     2:00000000000000000 SECTION LOCAL  DEFAULT    13:00000000000000000 SECTION LOCAL  DEFAULT    34:00000000000000000 SECTION LOCAL  DEFAULT    45:00000000000000000 SECTION LOCAL  DEFAULT    56:00000000000000000 NOTYPE  LOCAL  DEFAULT    5 $d
     7:00000000000000000 NOTYPE  LOCAL  DEFAULT    4 $d
     8:00000000000000000 SECTION LOCAL  DEFAULT    69:00000000000000000 NOTYPE  LOCAL  DEFAULT    6 $d
    10:00000000000000000 NOTYPE  LOCAL  DEFAULT    1 $x
    11:00000000000000000 SECTION LOCAL  DEFAULT    812:00000000000000140 NOTYPE  LOCAL  DEFAULT    9 $d
    13:00000000000000000 SECTION LOCAL  DEFAULT    914:00000000000000000 SECTION LOCAL  DEFAULT    715:00000000000000001 OBJECT  GLOBAL DEFAULT    5 tttt
    16:00000000000000001 OBJECT  GLOBAL DEFAULT    4 temp_1
    17:00000000000000011 OBJECT  GLOBAL DEFAULT    4 temp_2
    18:000000000000000044 FUNC    GLOBAL DEFAULT    1 fun
    19:00000000000000000 NOTYPE  GLOBAL DEFAULT  UND printf
    20:000000000000002c    80 FUNC    GLOBAL DEFAULT    1 mian

上述文件有fun和printf函数,fun函数能找到对应的定义,但是printf无法找到,前面ndx为UND(未定义)。

3.2、兼容C语言 – extern C

extern"C"{intfunc(int);int var;}

为什么这么做?
C++中编译后会将函数名或者变量名进行重新封装修饰,即:fun编译后会生成符号_ZN3fun3barE
在C中会生成_fun 或者 fun,具体看编译器的支持。
使用extern C后C++会将括号中的文件安装C语言的编译格式生成符号表。

/*d.cpp*/#include<stdio.h>#definePI(111)extern"C"{voidfunci(){;}}staticvoidfunc(float){;}voidffunc(int){;}intmain(){if(PI);return0;}

编译调试查看:

pi@NanoPi-NEO2:~/project/test$ g++-c d.cpp
pi@NanoPi-NEO2:~/project/test$ readelf -s d.o

Symbol table '.symtab' contains 14 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0:00000000000000000 NOTYPE  LOCAL  DEFAULT  UND 
     1:00000000000000000 FILE    LOCAL  DEFAULT  ABS d.cpp
     2:00000000000000000 SECTION LOCAL  DEFAULT    13:00000000000000000 SECTION LOCAL  DEFAULT    24:00000000000000000 SECTION LOCAL  DEFAULT    35:00000000000000000 NOTYPE  LOCAL  DEFAULT    1 $x
     6:000000000000000820 FUNC    LOCAL  DEFAULT    1 _ZL4funcf
     7:00000000000000000 SECTION LOCAL  DEFAULT    58:00000000000000140 NOTYPE  LOCAL  DEFAULT    6 $d
     9:00000000000000000 SECTION LOCAL  DEFAULT    610:00000000000000000 SECTION LOCAL  DEFAULT    411:00000000000000008 FUNC    GLOBAL DEFAULT    1 func
    12:000000000000001c    20 FUNC    GLOBAL DEFAULT    1 _Z5ffunci
    13:00000000000000308 FUNC    GLOBAL DEFAULT    1 main

func没有使用C++的符号命名方式。fun使用了C++的符号命名。
_Z5ffunci:
_Z:固定字符
5:函数名有5个字符
i:int类型(f:float,v:void。。。)

4、链接 – ld

根据上文,每个文件都会生成一张符号表,如a.o和b.o两个文件,如何将a.o和b.o链接在一起生成可执行文件?
链接方法有两种:
1、按照文件的顺序依次合在一起,这样每个文件都会有重复的.text、.data。。。等等。
2、将所有的相同属性的段合在一起,即text在一起,data在一起。(主流方案)
举例:

#include"stdio.h"#include"stdint.h"voidfun(uint8_t test){;}inttest(){fun(1);return0;}
#include"stdio.h"#include"stdint.h"intmain(){test();return0;}
gcc -c main.c main_1.c
ld main.o main_1.o -e main -o ab

-e main 表示将 main 函数作为程序入口,ld 链接器默认的程序入口为_start。
-o ab 表示链接输出文件名为 ab,默认为 a.out。

执行后生成的ab文件中所有的相同属性对会对应在一起。

pi@NanoPi-NEO2:~/project/test$ objdump -h main.o 

main.o:     file format elf64-littleaarch64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0.text         0000001800000000000000000000000000000000000000402**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1.data         0000000000000000000000000000000000000000000000582**0
                  CONTENTS, ALLOC, LOAD, DATA
  2.bss          0000000000000000000000000000000000000000000000582**0
                  ALLOC
pi@NanoPi-NEO2:~/project/test$ objdump -h main_1.o 

main_1.o:     file format elf64-littleaarch64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0.text         0000003000000000000000000000000000000000000000402**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1.data         0000000000000000000000000000000000000000000000702**0
                  CONTENTS, ALLOC, LOAD, DATA
  2.bss          0000000000000000000000000000000000000000000000702**0
                  ALLOC
pi@NanoPi-NEO2:~/project/test$ objdump -h ab

ab:     file format elf64-littleaarch64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0.text         000000c4  00000000004001200000000000400120000001202**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1.eh_frame     0000006000000000004001e800000000004001e8000001e82**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2.got          000000100000000000410fd8  0000000000410fd8  00000fd8  2**3
                  CONTENTS, ALLOC, LOAD, DATA
  3.got.plt      000000180000000000410fe8  0000000000410fe8  00000fe8  2**3
                  CONTENTS, ALLOC, LOAD, DATA
  4.data         0000000400000000004110000000000000411000000010002**1
                  CONTENTS, ALLOC, LOAD, DATA
  5.bss          0000000c  00000000004110040000000000411004000010042**1
                  ALLOC
  6.comment      0000002a  00000000000000000000000000000000000010042**0
                  CONTENTS, READONLY

查看生成的文件符号表:

pi@NanoPi-NEO2:~/project/test$ readelf -s ab 

Symbol table '.symtab' contains 20 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0:00000000000000000 NOTYPE  LOCAL  DEFAULT  UND 
     1:00000000004000b0     0 SECTION LOCAL  DEFAULT    12:00000000004000f8     0 SECTION LOCAL  DEFAULT    23:00000000000000000 SECTION LOCAL  DEFAULT    34:00000000000000000 FILE    LOCAL  DEFAULT  ABS main.c
     5:00000000004000b0     0 NOTYPE  LOCAL  DEFAULT    1 $x
     6:000000000040010c     0 NOTYPE  LOCAL  DEFAULT    2 $d
     7:00000000000000000 FILE    LOCAL  DEFAULT  ABS main_1.c
     8:00000000004000c8     0 NOTYPE  LOCAL  DEFAULT    1 $x
     9:00000000004001300 NOTYPE  LOCAL  DEFAULT    2 $d
    10:0000000000410fe8     0 NOTYPE  GLOBAL DEFAULT    2 _bss_end__
    11:0000000000410fe8     0 NOTYPE  GLOBAL DEFAULT    2 __bss_start__
    12:00000000004000c8    20 FUNC    GLOBAL DEFAULT    1 fun
    13:0000000000410fe8     0 NOTYPE  GLOBAL DEFAULT    2 __bss_end__
    14:00000000004000dc    28 FUNC    GLOBAL DEFAULT    1 test
    15:0000000000410fe8     0 NOTYPE  GLOBAL DEFAULT    2 __bss_start
    16:00000000004000b0    24 FUNC    GLOBAL DEFAULT    1 main
    17:0000000000410fe8     0 NOTYPE  GLOBAL DEFAULT    2 __end__
    18:0000000000410fe8     0 NOTYPE  GLOBAL DEFAULT    2 _edata
    19:0000000000410fe8     0 NOTYPE  GLOBAL DEFAULT    2 _end

每一个函数都对应唯一的地址。对于单个文件的编译中找不到的符号会临时用一个假地址代替,直到链接的时候才会查找真实地址并替换。
比如:没有链接前,main.c找不到test函数,就会设置test函数地址为0,
在这里插入图片描述
链接后的文件会填充对应的地址。
在这里插入图片描述

标签: linux 学习 运维

本文转载自: https://blog.csdn.net/qq_37280428/article/details/131270495
版权归原作者 Mr·赵 所有, 如有侵权,请联系我们删除。

“【Linux】程序员的基本素养学习”的评论:

还没有评论