Linux的开发工具(三)
条件编译
预处理本质:对代码进行裁剪
像网易云音乐有vip和普通用户,可以通过条件编译来,这样只用写一份代码,也只用维护一份代码,是vip就走vip代码,不是就普通用户代码,条件编译来动态裁剪。
1 #include<stdio.h>
2 #define M
3
4 int main()
5 {
6 #ifndef M
7 printf("free");
8 #else
9 printf("advance");
10 #endif
11
12 }
~
~
~
~
~
为什么C/C++编译,要先变成汇编
因为刚开始电脑都是用按键来控制的,高低电平对应1和0,所以是二进制来命令电脑,但是二进制麻烦,所以有了汇编语言,但也要有编译器,汇编语言也是文本所以要翻译成二进制
C语言直接变成二进制or翻译成汇编再翻译成二进制,减少成本,C语言到汇编是文本到文本相对简单,再汇编到二进制可以站在巨人的肩膀上不用自己写。
汇编语言的编译器,用二进制版汇编编译器编译汇编语言,在用汇编语言写汇编编译器,然后用二进制汇编编译器编译汇编语言编译器,这样汇编编译器就可以用了,来编译汇编语言,这个行为叫编译器的自举过程。
为什么要链接
预处理展开的是声明,没有实现
站在巨人肩膀上,把其它顶级大佬写的代码封装好,基本功能就不用自己写,直接写函数名,在链接时找到对应的实现方法
动态链接和静态链接
实际开发中,会出现多个源文件,而且多个源文件之间不是独立的,会存在多种依赖关系,如源文件可能要调用另一个源文件中定义的函数,但是每个源文件都是独立编译的,既每个.c文件都会形成一个.o文件,为了满足前面说的依赖关系,则需要将这些源文件产生的目标文件进行链接,形成一个可执行的程序。这个链接过程就行静态链接。
缺点:
浪费空间:每个可执行程序中对所有需要的目标文件都有一份拷贝,如果多个程序对同一个目标文件都有依赖,如调用printf函数,则多个程序都含有printf.o,所以同一个目标文件都在内存中有多个副本
更新困难:每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序。
动态链接的出现解决了静态链接的问题,基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时将它们链接在一起形成了一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。
root@iZbp1be068ksa92vuf0kbdZ:~/zym# gcc code.o -o code11
root@iZbp1be068ksa92vuf0kbdZ:~/zym# ls
code11 code.cpp code.o
root@iZbp1be068ksa92vuf0kbdZ:~/zym# ldd code11
linux-vdso.so.1 (0x00007ffec23cb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f45a0257000)
/lib64/ld-linux-x86-64.so.2 (0x00007f45a048e000)
root@iZbp1be068ksa92vuf0kbdZ:~/zym# ./code11
hello worldroot@iZbp1be068ksa92vuf0kbdZ:~/zym#
概念:库
系统把这些函数实现都被做到名为libc.so.6的库文件中去了,没有特别指定,gcc会收到系统的默认搜索路径,“/use/lib”下查找,也就是链接到libc.so.6库函数,这样实现函数printf,这就是链接的作用。
静态库和动态库
静态库是指编译链接时,把库函数的代码全加到可执行文件中,因此生成的文件比较大,但在运行时就不在需要库文件了,后缀名一般为“.a”
动态库在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,可以节省系统开销,动态库后缀为“.so”,libc.so.6就是动态库,完成链接后就可以生成可执行文件
gcc hello.o -o hello
gcc默认生成的二进制程序,是动态链接,可以通过file命令验证
hello worldroot@iZbp1be068ksa92vuf0kbdZ:~/zym# file code11
code11: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=eedbea476e4b714e5d707af0c59df9609b1fd209, for GNU/Linux 3.2.0, not stripped
(静态库和动态库名字都是.c加前面和后面组成的,动态库是前面+lib后面+.so.6)
举例:
小明考上了高中,但是他很喜欢打游戏,这个高中比较严格禁止电子产品,小明找到学长得知校外有网吧,小明从学长那里得到了网吧的地址,准备下午去上网,但是得先上课,小明的计划就是程序代码,到了1点小明要执行上网的程序,所以要去网吧上网,他要从学校跳到网吧,上网后又跳回到学校。小明是程序角色,学长是动态链接,高中是内存,网吧就是动态库,链接时得到了网吧地址,程序加载到内存中,程序开始时就知道了网吧的地址,所以执行上网就可以根据地址在动态库找到对应的函数。
例子二:
网吧被学校举办后只能关掉,但是小明没有网吧后成绩下滑,于是家长要求学校同意带电脑上学,但是下面一定要他上网吧的100号电脑,于是父亲找到老板要了100号机的配置信息配了一台一模一样的电脑放在了小明的宿舍,这时小明不用执行上网就要跳到校外去了,在学校里面就可以上网,这里把库的执行方法直接拷贝了一份到内存里,所以在执行程序时就直接有了实现方法,不用跳到别的地方。
执行静态链接代码:
gcc code .o -o code -static
程序加载到内存时,还需要把库也加载进来,如果其它程序也用到了这个库,那么只要第一次加载,后面的就不需要加载动态库了,直接在内存跳到实现方法,保证公共的代码只出现一份。
命令大部分由C写,指令依赖动态库,会加载动态库,其它程序就不用加载。
库的本质:被打包起来的.o文件
链接本质:把.o文件合在一起
粘滞位
在Linux系统中,`tmp`目录中的`t`权限代表的是“粘滞位”(Sticky Bit)。粘滞位是一种特殊的权限,它只适用于目录,而不适用于文件。当一个目录设置了粘滞位权限时,该目录中的文件只能由其所有者或者root用户删除或重命名,即使其他用户对该文件拥有写权限也无法删除或重命名这些文件。
例如,`/tmp`目录通常被设置为`drwxrwxrwt`,这意味着所有用户都可以读取、写入和执行该目录,但是由于设置了粘滞位,只有文件的所有者和root用户可以删除或重命名该目录下的文件。这样的设置可以防止一个用户删除或修改另一个用户在`/tmp`目录中创建的临时文件,从而增强了系统的安全性。
自动化构建工具
先创建Makefile文件,code:code.c表示的是源文件是code.c(code:是源文件为什么),gcc -o code code.c是依赖方法要生成一个可执行文件,然后用make指令,这时目录下就有code可执行文件了。
代码示例
root@iZbp1be068ksa92vuf0kbdZ:~/zym# mkdir mk
root@iZbp1be068ksa92vuf0kbdZ:~/zym# cd mk
root@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# touch Makefile
root@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# ll
total 8
drwxr-xr-x 2 root root 4096 Nov 24 11:18 ./
drwxr-xr-x 3 root root 4096 Nov 24 11:17 ../
-rw-r--r-- 1 root root 0 Nov 24 11:18 Makefile
root@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# vim Makefile
root@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# cat Makefile
code:code.c
gcc -o code code.c
root@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# ll
total 12
drwxr-xr-x 2 root root 4096 Nov 24 11:19 ./
drwxr-xr-x 3 root root 4096 Nov 24 11:17 ../
-rw-r--r-- 1 root root 32 Nov 24 11:19 Makefile
root@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# vim code.c
root@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# ll
total 16
drwxr-xr-x 2 root root 4096 Nov 24 11:20 ./
drwxr-xr-x 3 root root 4096 Nov 24 11:17 ../
-rw-r--r-- 1 root root 70 Nov 24 11:20 code.c
-rw-r--r-- 1 root root 32 Nov 24 11:19 Makefile
root@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# make
gcc -o code code.c
root@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# ll
total 32
drwxr-xr-x 2 root root 4096 Nov 24 11:20 ./
drwxr-xr-x 3 root root 4096 Nov 24 11:17 ../
-rwxr-xr-x 1 root root 15960 Nov 24 11:20 code*
-rw-r--r-- 1 root root 70 Nov 24 11:20 code.c
-rw-r--r-- 1 root root 32 Nov 24 11:19 Makefile
root@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# ./code
hello worldroot@iZbp1be068ksa92vuf0kbdZ:~/zym/mk# vim Makefile