引言:
现在是北京时间2023年6月14日8点16分,期末考试在即,重心可能得转移到考试上了。不过想到马上就可以回家陪家人过端午节,还是非常开心的。放暑假了就可以好好陪家人了。尝试一下换个环境复习吧,洗漱一下就去图书馆了。
sudo的介绍和配置
在之前介绍yum工具时,普通用户需要sudo对指令进行提权才能下载或卸载软件。那么sudo是什么呢?sudo要如何配置呢?下面且听我的介绍。
什么是sudo?
sudo是一个Linux/Unix操作系统中的命令,用于以超级用户(即root用户)的身份执行命令或访问系统资源。一般来说,普通用户无法访问某些系统资源或执行某些系统命令,而使用sudo命令可以暂时提升用户权限以执行这些操作。使用sudo命令需要输入当前用户的密码以确认身份。
没有sudo权限的现象
sudo的配置
第一步,用root账户打开sudoers配置文件
vim /etc/sudoers
第二步,将root那一栏的信息拷贝粘贴一份并在用户名处改成你要配置的用户,随后在低行模式下写入即可。
下面简单验证一下。
gcc/g++编译器的使用
gcc/g++基本使用
gcc 源文件.c -o
g++ 源文件.cpp/源文件.c -o
-o后面跟一个自定义程序的名字,如gcc 源文件.c -o mytest,那么编译器在生成可执行程序后就不会以默认的a.out来命名这个可执行程序,而是用mytest来作为可执行程序的名称。
g++编译cpp文件后,默认产生的可执行程序也是a.out。这说明gcc和g++是同根同源的。那么gcc可以编译cpp文件吗?g++可以编译c文件吗?
结论:gcc不能编译.cpp后缀的源文件。
结论:g++可以编译.c后缀的c源文件。但是平时建议使用gcc编译.c后缀的源文件。
程序的翻译过程
程序的翻译过程大致分为四种,分别是预处理、编译、汇编以及链接。下面我就简单给各位介绍一下这四种编译过程。
gcc的预处理过程
预处理是负责对源代码进行处理。此时,会完成以下工作:头文件展开、宏替换、注释删除以及条件编译等工作。处理完上述工作后,编译器会生成一个新的文本文件,以.i作为扩展名。下面我就在Linux环境中的gcc编译器下进行简单的演示。
gcc -E 源文件.c -o 新的文本文件.i
这里的-E选项其实就是告诉编译器,你翻译我的源代码,将预处理的工作完成后就停下来。
由于我们没有定义DEBUG宏,所以在条件编译后,.i文件中就是printf(“release\n”);这行代码。既然gcc可以进行一些列的文本操作,相应的也可以进行宏定义。下面就简单演示一下
gcc -E test.c -o test.i -DDEBUG
条件编译有什么用呢?这里就要聊一聊大家对于一些软件会有不同的定位。如我们用的vs,大部分的学生群体一般用的是社区版,有些在职的开发人员通常会使用专业版。通常,社区版只给一些最基础的开发包和开发工具。而专业版会提供更丰富更新的开发包和开发工具。提供这两个不同版本的厂商会维护两份代码吗?答案是不需要,因为这需要维护专业版的代码就可以了,通过条件编译进行代码的裁剪已达到相应功能的阉割,使产品的具有差异化。
拓展补充
为什么我们能在windows或者Linux下进行对应的c/c++开发呢?这是因为我们在windows下面安装了vs20xx,亦或者是我们的linux云服务器出厂自带了gcc/g++编译器。这些是我们能在不同平台下进行对应c/c++开发的因素也是第一步。但是,这里要强调的是头文件以及库文件同样是非常重要的。库文件和头文件的安装是第二步。这是因为库文件和头文件可以大大提升我们的开发效率,提升代码的复用性以及可维护性。而我们大家在windows环境下下载集成开发工具vs2019或是vs2022选择安装对应的开发包,本质其实就是在在下载库文件和头文件。
下面简单介绍一下如何查看Linux下的头文件库文件。查看Linux的头文件库文件所在位置指令
ls /usr/include/
我们也可以用vim打开对应的头文件库文件查看相应的代码,并在底行模式中进行搜索。
vim string.h
gcc的编译过程
编译的过程是让我们写的高级编程语言的源代码经过编译器的处理变成汇编代码。汇编代码是由一系列符号指令组成的,每个指令都代表一条机器语言指令。下面简单带大家看看gcc是如何让我们的源代码转化成汇编的。
gcc -S test.c -o test.s
汇编语言是计算机底层的语言,它也是一门独立的学科。汇编语言是计算机硬件的直接控制语言,它与机器语言一一对应,一条汇编指令对应一条机器指令。像上图中的一些指令如call指令、movl指令等本质上都是在进行寻址操作或者是根据地址进行调用操作的。我们无需要深入学习,只要能大概做一个了解就可以了。
gcc的汇编过程
汇编的过程是编译器将汇编代码转化成机器能识别的二进制指令。下面简单用gcc演示一下汇编的操作。
gcc -c test.c -o test.o
``
可以看到虽然给了.o文件可执行权限,但是它依旧不可以被执行。这是因为没有进行链接,不可以被执行。
gcc的链接过程
在程序翻译过程中的链接是指将编译器所产生的目标代码和库文件等合并成可执行文件的过程。链接过程也是程序翻译的最后一个阶段,完成链接之后,程序就可以被执行。下面依旧使用gcc进行简单的进行一个演示。
gcc test.o -o mytest
当然,直接使用gcc + 源文件也可以直接生成默认的可执行程序a.out。那么上述的那些选项记不住怎么办呢?这里介绍一个记忆技巧,我们看看键盘左上角有个ESC键,对应的就是预处理的-E选项,编译的-S选项以及汇编的-c选项。注意的是c是小写,其他两个选项是大写。生对应的文件分别是.i、.s、.o,可以记一下是国际标准组织ios。
库的介绍
上面在介绍编译器翻译程序的过程中介绍到在编译器链接的过程中会将头文件和库文件合并成可执行程序。什么是库文件呢?下面我就简单进行一个介绍。
我们在写c语言代码的时候难免要用printf输出、scanf输入。这两个库函数就是c标准库为我们提供的函数方法。当然了库的本质也是文件,在Linux中以.so(动态库)为后缀以及.a(静态库)为后缀都表示为库文件。在windows中,以.dll(动态库)为后缀以及以.lib(静态库)为后缀的文件我们称之为库文件。下面以Linux环境为例简单带大家看看库文件存放的位置以及命名规则
ls /lib64/libc.so*
方法是实现在库中的。库其实就是把不同的源文件(.c文件)进行一定的翻译,然后打包。这样就只需要提供一个库文件给用户使用即可,可以隐藏源文件的实现。库文件的出现给予我们站在巨人的肩膀上编程的机会,无需自己造轮子实现一些常用的库函数,当然我们在学习时,还是需要适度造轮子的。所以我们的写的可执行程序 = 库文件+头文件+我们写的源代码。
库的链接
库的链接分为两种:静态链接和动态链接。下面简单介绍一下这两种链接。
先介绍动态链接,动态链接需要动态库,而动态库就像是我们在以前上学时经常去的网吧。大家或多或少都因为家里不支持玩游戏,而偷偷跑去网吧开黑。这时候我们总能根据需求找到对应的网吧和小伙伴开黑。这就是我们的动态链接。有一天,网吧被查封了。我们大家伙就无法去上网了。这对应着动态库缺失后,许多依赖该动态库的程序无法正常运行。这是因为编译器在进行动态链接时,将方法的地址拷贝给我们的目标程序,一旦动态库缺失必定造成程序的错误。
我们在大学中或多或少都会配笔记本电脑。我们购买笔记本这一行为就类似于静态链接。而笔记本厂商就类似于静态库的角色。当我们已经买了笔记本电脑,但是厂商倒闭(静态库缺失),此时我们依旧可以正常使用我们的笔记本电脑。编译器进行静态链接时,会将对应的方法拷贝到我们的目标程序中,使得目标程序不再依赖静态库。
简单演示链接
下面简单演示一下动态链接。
gcc xxx.c -o xxx
ldd xxx
可以看到编译器默认是以动态链接进行链接的。如果我们想进行静态链接可以吗?答案是没问题。
gcc xxx.c -o xxx -static
file指令可以用于查看程序的链接方式
file 可执行程序
拓展补充
对于以下拓展内容仅仅只是介绍,相关验证等未来一一给大家提供。
1、如果没有静态库的话可以进行静态链接吗?答案是不行的。
2、若没有动态库,但有静态库并且gcc可以找到该静态库,可以进行动态链接吗? 答案是可以的。因为-static的本质是改变优先级。
3、日常中,我们使用的应用程序一定不是完全的静态链接或动态链接,是两者混合的。
动静态库的优缺
动态库的优点有资源利用率高(硬盘资源、内存资源、网络资源等),缺点为一旦库缺失,依赖库的各个程序都无法正常运行。
静态库的优点有各个应用程序不依赖于库,缺点为对于资源(硬盘资源、内存资源、网络资源等)的利用率低。
debug&&release
gcc默认编译生成的可执行程序是release版本,下面简单介绍一个指令来进行将gcc生成的可执行程序以debug版本发布。
gcc xxx.c -g
debug版本相比于release版本加了追踪调试信息所以体积更大。这是我们前面学习VS2019IDE时就已经介绍过了的,这里简单提一下。