文章目录
Linux基础开发工具使用
1.Linux软件包管理器 yum
1.1 什么是软件包?
在Linux系统下安装软件,一个通常的办法是下载到程序的源代码,并进行编译,得到可执行程序。但是这样有些麻烦,于是有些人就把一些常用的软件提前编译好,做成软件包(可以理解成windows上的安装程序)放在一个服务器上,通过包管理器可以很方便的获取到这个编译好的软件包,直接进行安装。
软件包和软件包管理器,就好比App和应用商店的关系。 yum是Linux下非常常用的一种包管理器,主要应用在Fedora、RedHat、Centos等发行版上。
需要注意的是:
要想使用yum,需要保证主机(虚拟机)网络畅通。
可以通过ping指令验证
ping www.baidu.com
1.2 查看软件包
1.2.1
通过yum list 命令可以罗列出当前一共有那些软件包,由于软件包的数目可能非常之多,这里需要用grep命令搭配管道筛选出我们需要的包。
其结果如下
软件包名称:主版本号,次版本号,源程序发行号-软件包的发行号,主机平台,CPU架构。
x86_64后缀表示64位系统的安装包,i686后缀表示32位系统安装包。选择包时要和系统匹配。
el7表示操作系统发行版的版本,el7表示的是centos7/redhat7。
最后一列,表示的是软件源的名称,类似于应用商店的概念。
1.2.2 如何安装和删除软件
1.安装软件
通过yum,我们可以通过很简单的一条命令完成gcc的安装。
sudo yum install gcc
gcc就是要安装的软件名。yum会自动找到都有哪些软件包需要下载,这时候敲 y 确认安装。出现complete字样,说明安装完成。
需要注意的是
①安装软件时由于需要向系统目录中写入内容,一般需要sudo或者切到root账户下才能完成。
如何使用sudo命令使得普通用户暂时取得root用户权限?
a.首先使用root用户登录系统,或者使用已经拥有sodu权限的用户登录
b.使用vi 或 vim 编辑 /etc/sudoers 文件,找到 root ALL=(ALL) ALL,在其下面添加一行。
例如:username ALL=(ALL) ALL,其中username 就是需要授权的普通用户名。
c.保存并退出文件。
②yum安装软件只能一个装完了再装另一个。正在yum安装一个软件的过程中,如果在尝试用yum安装另一个软件,yum会报错。
2.卸载软件
依然是一条命令
sudo yum remove gcc
gcc就是要卸载的软件名。
2.Linux开发工具
2.1 Linux编辑器 - vim使用
vi/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面。例如语法高亮,可视化操作不仅可以在终端运行,也可以运行于windows、mac os。
2.1.1 vim的基本概念
vim有着三种基本模式,分别是命令模式、插入模式和底行模式。
正常/普通/命令模式(Normal mode)
控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入插入模式(Insert mode)下,或者到底行模式(last line mode)。
插入模式(Insert mode)
只有在Insert mode下,才可以做文字输入,按[Esc]键可回到命令模式。
底行模式 (last line mode)
文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。在命令模式下,按 shift + : 即可进入该模式。
此外,vim还有多种模式,可以在底行模式下输入 :help vim-modes。即可查看vim的所有模式。
2.1.2 vim的基本操作
进入vim, 在系统提示符号输入vim及文件名称后,就进入vim全屏幕编辑画面:
vim test.c
不过有点要特别注意,就是你进入vim之后,是处于[正常模式],你要切换到[插入模式]才能够切换文字。
在vim编辑器中,可以通过以下几种方式从普通模式切换到插入模式:
按下 i 键,在光标所在位置插入文本。
按下 a 键,在光标所在位置之后插入文本。
按下 o 键,在光标所在行的下方插入新行并开始输入文本。
按下 O 键,在光标所在行的上方插入新行并开始输入文本。
按下 I 键,在光标所在行的行首插入文本。
按下 A 键,在光标所在行的行尾插入文本。
插入模式切换至正常模式。
目前处于插入模式,就只能一直输入文件,如果发现输错了字,想用光标键往回移动,将该字删除,可以先按以下[Esc]键转到[正常模式]在删除文字。当然,也可以直接删除。
退出vim及保存文件,在[正常文件]下,键入冒号 其实就是 shift + : 进入底行模式。然后输入:
w (保存当前文件)
wq (保存并退出)
q! (不保存强制退出)
2.1.3 vim正常模式命令集
a.移动光标:
vim可以直接用键盘上的光标来上下左右移动,但正规的vim是用小写英文字母 [h]、[j]、[k]、[l],分别控制光标左、下、上、右移一格。
除了基本的上下左右移动外,还有一些其他的光标移动命令:
0
:移到行首。$
:移到行尾。^
:移到当前行的第一个非空字符。w
:向右移动到下一个单词的开头。e
:向右移动到当前单词的结尾。b
:向左移动到上一个单词的开头。gg
:移动到文件的第一行。G
:移动到文件的最后一行。H
:移动到当前屏幕的第一行。M
:移动到当前屏幕的中间行。L
:移动到当前屏幕的最后一行。Ctrl + u
:向上滚动半屏。Ctrl + d
:向下滚动半屏。Ctrl + f
:向下滚动一屏。Ctrl + b
:向上滚动一屏。
b.删除文字:
x
:删除光标所在位置的字符。- #x : 删除光标所在位置的后面(包括其自身在内)#个字符
- X : 大写的X,每按一次,删除光标所在位置的前面一个字符
- #X : 删除光标所在位置的前面#个字符。
dw
:删除从光标位置开始到下一个单词开头之间的字符。d$
:删除从光标位置开始到当前行末尾之间的字符。dd
:删除当前行。- #dd : 从光标所在行还是删除#行。
dgg
:删除从光标所在行到文件第一行之间的所有行。dG
:删除从光标所在行到文件最后一行之间的所有行。d}
:删除从光标所在行到下一个空行之间的所有行。:n1,n2d
:删除从第n1行到第n2行之间的所有行。:nd
:删除第n行。:.,$d
:删除从当前行到文件末尾之间的所有行。:1,$d
:删除整个文件的所有行。
c.替换文字:
r : 替换光标所在处的字符。
R :替换光标所到之处的字符,直到按下Esc键为止。
d.撤销上一次操作:
u : 如果误操作,可以马上按下u,回到上一个操作。按下多次u,可以执行多次恢复。
ctrl + r :撤销的恢复。
e.更改
cw : 更改光标所在处的字到字尾处。
c#w : 更改#个字符。
2.1.4 vim底行模式命令集
在使用底行模式之前,需要保证目前的vim编辑器的模式处于正常模式,在键入 [ : ]冒号即可进入底行模式。
a.列出行号:
[set nu] :会在文件中的每一行前面列出行号。
b.跳到文件中的每一行:
[ # ] : # 表示一个数字,在冒号后输入一个数字,在按回车键就会跳到该行了。如输入数字15,再回车就会跳到文章的第15行。
c.查找字符:
[/关键字] :先按[ / ]键,再输入需要寻找的字符,如果第一次找的关键字不是想要的,可以一直按[n]往后寻找到需要的关键字为止。
[?关键字] :先按[?]键,在输入想要寻找的字符,如果第一次寻找的关键字不是想要的,可以一直按[n]寻找下一个匹配项。
看起来这两种方式一摸一样,但其实两种方式有着细微的差别。其中 [/]是往后寻找,而[?]是向前寻找。
2.1.5 vim配置
a.配置文件的位置
1.在目录/ect/下面,有一个名为vimrc的文件,这是系统中公共的vim配置文件,对所有用户都有效;
2.在每个用户的主目录下,都可以自己建立私有的配置文件,命名为:“.vimrc"。例如,/root目录下,通常已经存在一个.vimrc文件,如果不存在,则自己创建一个;
3.使用“ su 用户名 ”切换成用户自己,执行“ cd ~ ”进入自己的工作目录;
4.执行“ vim .vimrc ”打开自己目录下的.vimrc文件。
b.
以下是一个已经配好的vim配置,可以自行按照其上的说明安装使用。
2.2 Linux编译器-gcc/g++
2.2.1背景知识
编译器编译文件的过程如下
a.预处理:预处理器处理以 “#”开头的预处理指令,例如宏定义、头文件包含等。预处理器会对源代码进行处理,生成一个被称为展开代码的中间文件,通常以 .i 为后缀,表示预处理后的代码文件。
b.编译:编译器将展开代码翻译成汇编语言,生成相应的汇编代码。在这个阶段,编译器会检查语法错误、类型错误等,并进行优化。这个阶段处理完的文件通常以 .s 为后缀,表示生成的汇编代码文件。
c.汇编:汇编器将汇编代码转换成机器码,生成目标文件(通常以.obj为后缀或.o为扩展名)。目标文件包含了机器指令以及与之相关的符号信息。
d.链接:链接器将目标文件和其他需要的库文件进行链接,生成可执行文件。链接的过程包括符号解析、地址重定位、符号表生成等。链接器会解析引用的函数、变量,将它们与定义进行匹配,并将各个模块之间的依赖关系处理好。
链接的过程需要用到库文件,而库文件一般分为静态库和动态库两种。
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不在需要库文件了。其后缀名一般为 .a 。
动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样就可以节省系统的开销。动态库一般后缀名为.so。 gcc在编译时默认使用动态库。完成了链接之后,gcc就可以生成可执行文件。
2.2.2 gcc
1.要想使用gcc编译文件,可以按照如下步骤
a.保证如今处于源代码所在的目录
b.在终端中使用以下命令进行编译:
gcc <source_file.c> -o <output_file>
其中,<source_file.c>是要编译的源代码文件的名称,<output_file>是生成的可执行文件的名称。
c.按下回车键执行命令,gcc将会将源代码编译成可执行文件。
d.如果编译过程中没有错误,就可以在同一目录下找到生成的可执行文件。
2.gcc选项
-c
:只进行编译,生成目标文件而不进行链接。-o <file>
:指定输出文件的名称。-E
:只进行预处理,生成预处理后的代码。-S
:只进行编译,生成汇编代码。-g
:生成调试信息,以便在调试程序时使用。-Wall
:启用所有警告信息。-Werror
:将警告视为错误。-O<level>
:指定优化级别,例如-O1
表示启用一些基本的优化,-O2
表示更高级别的优化。-std=<standard>
:指定使用的语言标准,如-std=c++11
表示使用C++11标准。-I<dir>
:添加包含文件的搜索路径。-L<dir>
:添加库文件的搜索路径。-l<library>
:链接时使用指定的库。-D<macro>
:定义预处理宏。-U<macro>
:取消定义预处理宏。-shared
:生成共享库文件。-static
:生成静态可执行文件。
2.2.3 gdb使用
1.背景
程序的发布方式有两种,debug模式和release模式
Linux gcc/g++出来的二进制程序,默认是release模式。要想使用gdb调试,必须在源代码生成二进制程序的时候,加上 -g选项
gcc -g <source_file.c> -o <output_file>
2.开始使用
首先需要确保处于文件所在的目录。然后输入以下命令,开始使用gdb调试。
gdb <executable_file>
然后gdb启动后,可以输入以下命令:
list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
list/l 函数名:列出某个函数的源代码。
r或run:运行程序。
n 或 next:单条执行。
s或step:进入函数调用
break(b) 行号:在某一行设置断点
break 函数名:在某个函数开头设置断点
info break :查看断点信息。
finish:执行到当前函数返回,然后挺下来等待命令
print§:打印表达式的值,通过表达p 变量:打印变量值。
set var:修改变量的值
continue(或c):从当前位置开始连续而非单步执行程序
run(或r):从开始连续而非单步执行程序
delete breakpoints:删除所有断点
delete breakpoints n:删除序号为n的断点
disable breakpoints:禁用断点
enable breakpoints:启用断点
info(或i) breakpoints:参看当前设置了哪些断点
display 变量名:跟踪查看一个变量,每次停下来都显示它的值
undisplay:取消对先前设置的那些变量的跟踪
until X行号:跳至X行
breaktrace(或bt):查看各级函数调用及参数
info(i) locals:查看当前栈帧局部变量的值
quit:退出gdb
2.2.4 Linux项目自动化构建工具 make/Makefile
1.背景:
一个工程中的源文件有很多,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
makefile带来的好处就是 – 自动化编译。一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具。
make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
例如:
使用以下代码,编辑一个Makefile文件
vim Makefile
然后输入以下代码;
1 .PHONY: all clean
2 all:
3 gcc -E hello.c -o hello.i
4 gcc -S hello.i -o hello.s
5 gcc -c hello.s -o hello.o
6 clean:
7 rm -f hello.i hello.s hello.o hello.c
随后使用 vim hello.c 。创建hello.c文件。
输入以下代码:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
然后保存退出。
以下命令生成 hello.i文件 ,生成预处理后的代码文件:
gcc -E hello.c -o hello.i
以下命令生成hello.s
文件,生成
gcc -S hello.i -o hello.s
以下命令生成hello.o
文件,生成目标文件(包含机器码和符号信息):
gcc -c hello.s -o hello.o
然后在当前目录下使用make命令就可以看到以下文件
然后使用make clean命令就可以删除以上文件。因为我们创建的Makefile文件的代码是这样的
.PHONY:clean
clean:
rm -f hello.i hello.s hello.o hello.c
2.原理;
make命令是如何工作的?
在默认的方式下,也就是我们只输入make命令,那么
- make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
- 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“hello”这个文件,
并把这个文件作为最终的目标文件。 - 如果hello文件不存在,或是hello所依赖的后面的hello.o文件的文件修改时间要比hello这个文件新(可
以用 touch 测试),那么,他就会执行后面所定义的命令来生成hello这个文件。 - 如果hello所依赖的hello.o文件不存在,那么make会在当前文件中找目标为hello.o文件的依赖性,如果
找到则再根据那一个规则生成hello.o文件。(这有点像一个堆栈的过程) - 当然,你的C文件和H文件是存在的啦,于是make会生成 hello.o 文件,然后再用 hello.o 文件声明
make的终极任务,也就是执行文件hello了。 - 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文
件。 - 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,
而对于所定义的命令的错误,或是编译不成功,make根本不理。 - make只管文件的依赖性,即如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,
make就不工作啦。
2.3 Linux第一个小程序 - 进度条
#include <stdio.h>
int main()
{
printf("hello Makefile!\n");
sleep(3);
return 0;
}
在Linux系统下运行上述代码,会直接在屏幕上打印hello Makefile!,然后睡眠三秒。
#include <stdio.h>
int main()
{
printf("hello Makefile!");
sleep(3);
return 0;
}
在Linux系统下运行上述代码,会睡眠三秒,然后在屏幕上打印hello Makefile!。
#include <stdio.h>
int main()
{
printf("hello Makefile!");
fflush(stdout);
sleep(3);
return 0;
}
在Linux系统下运行上述代码,会直接在屏幕上打印hello Makefile!,然后睡眠三秒。这段代码之所以同第一段效果相同,是因为使用了fflush函数,将缓冲区中的数据立即刷新出来。
这是因为其采用的缓冲方式是行缓冲方式:
在行缓冲方式下,输出数据会被存储在缓冲区中,直到缓冲区被填满、遇到换行符"\n"或显示刷新刷冲区时才会被发送到输出设备。
2.3.1 进度条
#include <unistd.h>
#include <string.h>
#include <stdio.h>
int main()
{
int i = 0;
char bar[102];
memset(bar, 0 ,sizeof(bar));
const char *lable="|/-\\";
while(i <= 100 ){
printf("[%-100s][%d%%][%c]\r", bar, i, lable[i%4]);
fflush(stdout);
bar[i++] = '#';
usleep(10000);
}
printf("\n");
return 0;
}
首先定义一个字符数组bar 用于表示进度条,初始时所有位置都为空格。
char bar[102];
然后定义一个字符数组 lable,用于存储五种字符,用以显示进度条动画。
const char *lable="|/-\\";
使用memset()函数将数组bar中的所有元素初始化为0,即空格。
memset(bar, 0 ,sizeof(bar));
使用一个循环,循环条件为 i <= 100,表示进度条进度。
在循环中,使用printf()函数打印进度条,格式化输出字符串包括进度条、百分比和进度条样式字符。
[%-100s]
表示打印一个长度为100的进度条,左对齐。[%d%%]
表示打印当前百分比值。[%c]
表示打印进度条样式字符。\r
表示将光标移动到行首,使得下一次输出会覆盖当前行的内容。
printf("[%-100s][%d%%][%c]\r", bar, i, lable[i%4]);
使用ffush(stdout)函数刷新标准输出缓冲区,使得进度条立即显示在终端上。
将进度条数组bar中的当前位置 i 处设置为 # ,表示进度的增加。
bar[i++] = '#';
使用usleep()函数暂停程序一段时间(10毫秒),以控制进度条的刷新速度。
每次循环结束后,i增加1,进入下一次循环,直到完成百分比达到100。
循环结束后,使用 printf("\n")
打印一个换行符,使得进度条的最后一行与其他输出内容分隔开。