这篇文章主要涉及sudo指令进行提权的方法,gcc/g++的使用并且提及了一些make、makefile
sudo指令
在前几篇文章中,我们先后了解了对于不同的角色来说,可以进行不同的操作,而对于新建的普通用户是不能进行权限提升的,这是由于新用户还没有添加到信任白名单(sudoers file)中。
查看信任白名单的属性,可以发现user以及other都是root,这也就规定了修改这个白名单的人只能是root账户,也就是管理员。
下面进入roor账户,在信任白名单中添加新的用户。
进入vim编辑器。
找到与这种格式相同的,复制这行,并将新用户也设置成信任白名单里的人。
【注意】调出行号,使用set nu;复制yy;粘贴p。
然后wq!强制写入退出即可。这样我们的新建用户就可以进行sudo提权了。
简单测试之后,就可以知道新用户是可以使用sudo进行权限的提升了。
Linux编辑器——gcc/g++的使用
首先声明gcc与g++的使用是没有大的差别的,gcc只能编译C语言,g++建议只编译C++。
通过以上指令,简单测试了使用gcc编译c语言。
下面对gcc编译器进行详细的一个介绍:
背景知识
使用gcc进行编译的过程分为四个过程:
- 预处理(进行宏替换)
- 编译(生成汇编)
- 汇编(生成机器可识别代码)
- 链接(生成可执行文件或库文件)
预处理阶段
在预处理阶段,主要干下面这四个事情:
- 去注释
- 头文件展开
- 宏替换
- 条件编译
观察对比code.c文件与code.i文件,可以发现在预处理阶段,进行了头文件展开。
我们可以在原代码中添加一些信息,再进行对比。
通过对比,可以发现预处理阶段,去掉了注释,进行了头文件展开,宏替换。
问题:为什么能够在Windows或者Linux上进行C\C++或者其他形式的开发呢?
答:我们的系统中一定要提前或者后续安装上C/C++开发相关的头文件,原文件。C/C++开发环境不仅仅指的是vs,g++,gcc,更重要的是语言本身的头文件或库文件。
查看Linux下头文件的存储路径
其实类似于在安装vs2022的时候,选择对应的开发包,同步也在下载C语言的头文件和库文件,同时,C的头文件和库文件也在windows存在。
在预处理阶段,除了有上述内容以外,还需要验证条件编译。
我们先对原来的代码进行修改。
通过简单的debug模式的编译,可以测试条件编译。
问题:条件编译有什么用?
举个例子:软件有社区版(免费),也有专业版(付费)。对于提供这些软件的公司来所,需要写俩份代码吗?并不会,公司会根据不同的编译条件,裁剪掉社区版不需要的功能即可,这就是条件编译的场景。
编译阶段
编译阶段主要是生成汇编。
问题:预处理之后还是C语言吗?
是的,C语言变得更加干净了。
汇编阶段
汇编阶段生成机器可识别代码。
可以使用二进制查看工具查看代码
链接阶段
在链接阶段主要生成可执行代码或者库文件。
直接生成可执行代码
我们一般进行编译不会将.c文件分成四个阶段进行编译,而是使用默认直接形成可执行程序。
gcc code.c 默认直接形成可执行程序
gcc code.c -o code 如果需要命名,推荐使用这种方式
gcc -o code code.c
总结
预处理阶段(进行宏替换)
- 预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
- 预处理指令是以#号开头的代码行
- 例子:gcc -E code.c -o code.i
- 选项-E,该选项的作用是让gcc在预处理结束后停止编译过程。
- 选项-o,是指目标文件,.i 文件为已经预处理的C原始程序。
-E 告诉gcc,从现在开始进行程序的翻译,将预处理工作做完就结束。
编译阶段(生成汇编)
- 在这个阶段中,gcc首先要检查代码的规范性,是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。
- 用户可以使用-S选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
- 例子:gcc -S code.i -o code.s
-S 告诉gcc,从现在开始进行程序的翻译,将编译工作做完就结束。
汇编阶段(生成机器可识别代码)
- 汇编阶段是把编译阶段生成的.s文件转成目标文件
- 在此可以使用选项-c就可以看到汇编代码已经转换为.o的二进制目标代码了
- 例子:gcc -c code.c -o code.o
-C 告诉gcc,从现在开始进行程序的翻译,将汇编工作做完就结束。
code.o 可重定位目标二进制文件,简称目标文件——>Windows下的.obj文件,这种.o文件不能独立执行,虽然已经是二进制文件,需要经过链接才能执行。
链接(生成可执行文件或者库文件)
- 在成功编译之后,就进入了链接阶段
- 例子:gcc code.o -o code
- 将可重定位目标二进制文件和库链接形成了可执行程序。
如何记忆?
键盘左上角——ESc(选项),镜像文件的后缀——iso(文件后缀)
讨论链接
库,给我们提供了方法的实现。就比如C语言的标准库——本质上就是一个文件,是由路径的。
函数库
我们的C程序中,并没有定义“printf”的函数实现,并且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么这些函数是在哪里实现printf函数的呢?
答:系统把这些函数实现都被做到名位libc.so.6的库文件中去了,在没有特别指定时,gcc会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。
函数库一般分为静态库和动态库俩种。
- 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但是在运行时也就不再需要库文件了。其后缀一般为“.a”.
- 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为".so",如前面所述的libc.so.6,如前面所述的libc.so.6就是动态库。gcc在编译时默认使用动态库。完成链接之后,gcc就可以生成可执行文件。
- gcc默认生成的二进制程序,是动态链接的,这点可以通过file命令验证。
Linux下的动、静态库后缀
.so(动态库),.a(静态库)
Windows下的动、静态库后缀
.dll(动态库),.lib(静态库)
一般来说库都有自己的命名规则的:libname.so.XXX
我们的机器上,默认只会安装动态库,静态库默认是没有安装的。 编译型语言,安装开发包的时候,必定是下载安装对应的头文件,库文件。
方法的实现就是在库中,库其实就是把源文件(.c),经过一定的翻译,然后打包只给提供一个文件即可,不用给提供太多的源文件,也可以达到隐藏源文件的目的。
头文件提供方法的声明,库文件(不让我们做重复工作,站在巨人的肩膀)提供方法,再加上你的代码,就等于一款软件。
gcc选项
- -E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面。
- -S 编译到汇编语言不进行汇编和链接
- -c 编译到目标代码
- -o 文件输出到文件
- -static 此选项对生成的文件采用静态链接
- -g 生成调试信息。GNU调试器可利用该信息。
- -shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库。
- -O0
- -O1
- -O2
- -O3 编译器的优化选项的四个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
- -w 不生成任何警告信息
- -Wall 生成所有警告信息
.o文件和库是如何链接的
1.动态链接与静态链接
举个例子:在张三的高中里面,没有娱乐设施,所以张三和他的同学一直偷偷拿手机,但是张三拿手机和别人不一样,他是为了方便学习才拿的手机,他是为了抄作业才拿的手机,但是在学校的旁边有一个小卖部,里面可以进行充电,张三和他的同学经常去小卖部进行充电。学校旁边又开了一个小卖部,他也准备开放充电服务,但是学生不买他的账,不去他那里充电,有一天学校领导发现了,就不让这个小卖部继续充电了,导致张三和他的朋友没法继续抄作业,后面的作业也没有办法进行了。
这里的小卖部就是动态库——共享库。
共享库只需要有一个就可以了。
动态库不能缺失,一旦对应的动态库缺失,影响的不止一个程序,可能导致很多程序都无法正常进行。
使用指令:ldd code 查看依赖的动态库
后面呢,小卖部不打算让学生充电了,开始给学生卖充电宝了。
而这个充电宝就类似于静态库。
在编辑器使用静态库进行静态链接的时候,会将自己的方法拷贝到目标程序中,改程序一会不用再依赖静态库。
2.验证
在Linux中,gcc在编译程序形成可执行程序,默认采用就是动态链接——提供动态库。
使用指令:gcc code.c -o code-static -static
这是形成静态链接,动态链接的内存小于静态链接的内存。
在Linux中,如果要按照静态链接的方式,进行形成可执行程序需要添加-static选项——提供静态库。
1.如果我们没有静态库,但是就要使用-static,行不行?不行
2.如果我们没有动态库,只有静态库,而且gcc能找到?能,gcc默认优先使用动态链接,-static的本质就是改变优先级。
3.形成的可执行程序不一定是纯的全部动态链接或者静态链接,可能是混合的。
-static的本质:要求所有的链接都变成静态链接。
执行指令:file code 查看执行程序是动态还是静态的。
3.动态、静态链接的优缺点?
动态链接
动态库因为是共享库,可以有效的节省资源(磁盘空间,内存空间,网络空间);但是动态库一旦缺失,导致各个程序都无法运行
静态链接
静态库不依赖库,程序可以独立运行;但是静态库体积大,比较消耗资源。
debug&&release
debug 可以被追踪,调试
因为形成的可执行程序的时候,添加了debug信息。
gcc code.c -o code -g
gcc code.c -o code-static-debug -static -g
证明是否添加了debug信息,readelf指令可以读取可执行程序对应的二进制的构成
readelf -s code-debug
readelf -s code | grep -i debug
readelf -s code-debug | grep -i debug
make/makefile指令
make:是一条指令
makefile:是一个当前目录下的文件
先创建Makefle的一个文件,打开Makefile
第一行依赖关系,第二行依赖方法。
要创建,也需要清理:
先大概了解一些,后面再细细讲述。