赞
踩
Linux中的基础开发工具及其使用,包括yum(软件包管理器)、vim(编辑器)、gcc/g++(编译器)、makefile(项目自动化构建工具)、gdb(调试器)等。
我们在Linux下安装一个软件通常是下载程序的源代码,继续编译得到它的可执行程序。但是这样做比较麻烦,因此有一些人将常用的一些软件提前编译好做成软件包(相当于windows下的软件安装包)放在服务器上,通过软件包管理器可以获得这个编译好的软件包,直接安装可执行程序。
这一行为必须通过互联网;
答案是在别人的电脑上(远端服务器上,云服务器);
用现实中的例子,根据对象的不同,查找软件安装包的方式也不同:
a.电脑:搜索软件官网
b.手机:手机的应用商店(当然,应用商店也只是手机上的一个app)
c**.Linux:软件包管理器(相当于应用商店)**
(1)企业、组织、个人为了获得某种利益提供了软件包
(2)提供了软件包后,一般将他们放在那里?
a.电脑:软件官网
b.手机:手机应用商店——提供商的服务器
yum(Yellow dog Updater, Modified)是Linux下非常常用的一种包管理器. 主要应用在Fedora, RedHat,Centos等发行版上。
关于yum的所有操作必须保证主机(虚拟机)网络通畅,因此需要通过ping指令验证:
ping www.baidu.com
通过yum list命令可以罗列出当前公有那些软件包,因为软件包的数目会比较多,我们可以用grep命令筛选出我们所关注的软件包。
yum list | grep lrzsz
软件包名称:主版本号.次版本号.源程序发行号-软件包的发行号.主机平台.cpu架构。
"x86_64"后缀表示64位系统的安装包,“i686"后缀表示的是32位系统的安装包,选择安装包要与系统匹配。(操作系统的体系结构)
"el7"表示操作系统发行版的版本。“el7”表示centos7/redhat7。“el6”表示centos6/redhat6。
base表示“软件源”的名称,类似于手机上的XXX应用商店。
sudo yum install -y sl
-y
则无需确认)。该软件可以实现windows和Linux的交互,使windows机器于远端的Linux机器通过xshell传输文件,安装完毕后可以通过拖拽的方式将windows中的文件传给Linux。
sudo yum remove -y sl
-y
则无需确认)。ls /etc/yum.repos.d
1.备份原始的yum源(避免新的yum源有问题,同时导致不能返回原始yum源的情况)
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS.repo_tmp
2.下载阿里yum源配置文件
wget https://mirrors.aliyun.com/repo/Centos-7.repo
3.使用该yum源
将下载好的新yum源重命名为CentOS-Base.repo
当然如果使用的是云服务器就不需要更换yum源了(云服务器都是使用国内的镜像源)
官方软件集(centos、Ubuntu、kail等)中的软件都是经历长期使用确定稳定安全高效的,当然也存在非官方的软件集合(yum源一般称为epel)里面的软件都是还在试用的软件(有机会加入到官方)。
epel-release的安装(非官方扩展源)
yum install -y epel-release
如果在安装软件时,没有在官方软件集中找到官方的下载链接,则yum会自动去epel-release中查找。
vim是Linux下一种功能强大,有多种模式的编辑器。
vim有三种常用模式,分别是命令模式、插入模式、底行模式。
i
即可进入:
(shift + ;)即可进入在系统的提示符号输入vim及文件名称后,默认进入vim全屏幕编辑画面
$ vim test.c
输入 a
:从光标当前位置开始输入文字;
输入 i
:从光标的所在位置的下一个位置开始输入文字;
输入 o
:在文章刚开始插入新的一行,即,从文首开始输入文字。
从插入模式返回正常模式,按Esc
输入:
从底行模式返回正常模式,按Esc
[h] [j] [k] [l]
分别控制光标左、下、上、右移动[G]
光标移动到文本的末尾[gg]
光标移动到文本开始[$]
光标移动到光标所在行的行尾[^]
光标移动到光标所在行的行首[n + shift + g]
光标移动到第n行[x]
每按一次。删除光标位置的一个字符[n + x]
删除光标位置起的n个字符[X]
删除光标所在位置的前一个字符[n + X]
删除光标位置的前n个字符[dd]
删除光标所在行[n + dd]
删除光标所在位置起的n行[yy]
复制光标所在行到缓冲区[n + yy]
复制从光标所在行起的n行到缓冲区[p]
将缓冲区的内容粘贴到光标所在位置[yy + p]
复制粘贴[dd + p]
剪切[r]
替换光标所在位置的一个字符(支持nr
,将光标所在位置起的n个字符转化为一个字符)[shift + ~]
将光标所在位置的字母进行大小写转化(一直按着可以自动转换到这一行结束)[R]
替换光标所到之处的字符,直到按下Esc
键[u]
回到上一个操作(将该命令撤销),按多次[u]
可以执行多次撤销操作。[ctrl + r]
撤销的恢复(相当于撤销撤销这个操作)首先确定您已经处于底行模式。
set nu/nonu
列出行号/取消行号
vs copy.c
同时打开多个文件(代码中的copy.c是文件名),但是只有一个光标。光标的意义在于选中的行或屏幕。
光标跨屏:
ctrl + ww
底行模式中,不需要退出vim,只需要在指令前加上!
,即可强制执行shell指令。
!gcc test.c-o test
!./test
将要替换的命令替换为替换后的命令。
%/需要替换的命令/替换后的命令/g
wq
单独的w是保存文件,单独的q是退出文件,两个一起是保存并退出文件。
如果文件提示无法退出,可以在q之前加上!,强制退出。
没有进行配置的vim和记事本没有多大区别比较难使用,为了方便使用,我们要对vim进配置。
注意:vim的配置是一人一份的并不会互相影响,虽然大家用的是一个vim运行程序,但是大家的vim配置不同(每个成员在自己的家目录下有属于自己的vim配置)。
vim的配置是在家目录下的.vimrc
文件中,可以在该文件中添加一系列的命令。因此vim的配置其实就是修改.vimrc
文件。
在正式介绍编译器之前,我们先回顾一下编译链接的过程。
头文件展开、宏替换、条件编译、去掉注释。
gcc -E test.c -o test.i
从现在开始进行程序的翻译,直到预处理结束停下。
头文件展开:
去掉注释:
检查代码的规范性,以及是否存在语法错误等,确定无误后将代码编译为汇编语言。
gcc -S test.i -o test.s
从现在开始,进程程序的翻译工作,直到编译结束文件变成汇编后,就停下来。
将汇编语言转换为二进制语言(并非可执行程序,是二进制目标文件)
gcc -c test.s -o test.o
从现在开始,进行程序的翻译工作,做完汇编工作后,变成可重定向目标二进制文件,就停下来。
可以发现我们看不懂这些乱码,但是用命令od test.o
就可以将它转化为我们可以看懂的01二进制文件
链接的过程就是,将目标文件与标准库链接起来,形成一个可执行程序的过程。
gcc test.o -o test
链接的过程形成了可执行程序(test是我们自定义的可执行程序文件名,可以进行修改)
可以看到整个过程形成的所有的文件:
我们自己写的代码和库是两码事,我们自己写的程序中没有定义printf
等函数的具体实现,且在预编译中包含的stdio.h
中也只有这些函数的声明,只有在链接的时候该函数的实现才与我们的代码关联起来,那么这类函数是在哪里实现的呢?
答:这类函数都被实现到文件名为libc.so.6
的文件中,在没有特别指向时,gcc会到系统默认的搜索路径/usi/lib
下进行寻找。即,链接到libc.so.6库函数中去,这也是链接的作用,将库函数的实现与库函数的声明关联起来。
查看该文件:
ls /lib64/libc.so.6 -l
为了让我们站在巨人的肩膀上,减少我们的开发成本。
gcc meytest.c -o mytest.s
Linux下形成一个可执行文件使用的链接默认是动态链接。如果要求是静态链接,就必须在命令尾部加上 -static,如下:
gcc meytest.c -o mytest.s -static
从前,在XXX学校,有一个叫张三的学生,他每天的生活都很自律。每天都会严格执行自己的计划清单,清单内容:数学、语文、英语、上网、复习。他住在学校的宿舍里,身边有数学、语文、英语的学习资料,但是没有上网的工具。为了顺利执行计划,张三询问他的学长,学校附近是否存在网吧,学长告诉张三,出了学校北门往东走500米左右就到XXX网吧。因此张三先执行学习数学、语文、英语的计划,然后按照学长给他的地址到达XXX网吧进行上网,然后再回来复习今天的内容。
上面的故事可以参考下图进行理解。
如果将张三比作程序,则张三每日执行的计划清单就是程序员所写的代码,而其中上网这一项,则是程序要调用库函数。程序跳转到函数库中执行所需的库函数,执行完毕后再回到代码中继续向后执行。(这种调用库函数的方法称为动态链接)
动态链接形成的可执行的程序小。
节省资源——内存、磁盘。
方便下载。
受库的升级或者被删除的影响。
前几日由于受到学校的举报,学校附近的网吧都被关闭了。好在,张三的父母比较开明,也很信任自己的孩子,就给张三买下了张三常在网吧中学习的那台机子。在这之后,张三执行每日计划就不需要跑去外面的网吧,他在宿舍中就可以执行上网这一项内容,然后正常执行每日计划。
程序将所需的库函数从函数库中拷贝了一份,然后就不需要再进行跳转到函数库中执行库函数了。(这种调用库函数的方法称为静态链接)
不受库的升级或者被删除的影响。
形成的可执行程序体积太大。——网络、磁盘、内存。
同一个库函数可能会有多个C程序调用,此时使用静态链接就会导致代码冗余的问题。
不是,如果要静态链接的话,系统中必须存在.a结尾的静态库。因为,动态链接找动态库,静态链接找静态库。
去掉前缀lib,去掉后缀.so 剩下的就是库名称。动态库的后缀是.so 静态库的后缀是.s
eg: libC.so =》 C标准库
libXXXX.so
libYYYY.a
系统本身为了支持我们编程,给我们的程序提供了什么呢?
系统给我们提供的标准库.h(告诉我们怎么用),标准的动静态库.so/.a(告诉我们,方法实现我有,有需要就来找我)。
我的代码 + 库的代码 = 可执行程序。
上面的内容只在Linux下有效吗?windows下原理是一样的。(windows中静态库.dll,静态库.lib)同时windows下默认的默认链接也是动态链接。
makefile是一个文件,make是一个命令(执行makefile中的命令)。
makefile存在的意义,是为了构建项目(做的一件事情),做一件事情需要:a.依赖关系,b.依赖方法。
依赖关系,用哪个源文件生成目标文件;
依赖方法,如何用源文件生成目标文件。
例子:你去向你爸要生活费,会说爸,给我点生活费。
依赖关系:你和你爸是父子关系;
依赖方法:你爸给你打钱。
因此,makefile内部要保存大量的依赖关系和依赖方法。
例子:
第一行是依赖关系(mytest文件的形成依赖mytest.c文件),第二行是依赖方法(mytest.c文件经过编译形成mytest文件)
注意:第二行的最开始空白是一个Tab而不是几个空格。
make会执行第一个目标文件的生成语句
make 目标文件文件名 会执行指定的文件语句。
根据目标文件和它依赖的文件的修改时间差(关于时间的具体内容参见下文):如果它所依赖的文件修改时间在目标文件修改时间之前,则不需要再进行重新生成目标文件;如果它所依赖的文件修改时间在目标文件修改时间之后,则需要再重新生成目标文件。
一旦目标文件被设置为伪目标文件,即用.PHONY:
进行修饰,则目标文件每一次都将无视修改时间,即必须重新生成。
如果要将上面例子的每个步骤都进行执行的话,则需要如下图的代码:
make在缺省情况下(不指定目标文件),会只执行第一个目标文件的代码。如果第一个目标文件所依赖的文件还没有生成,就会去生成所依赖的文件(这一过程类似栈的规则:先进后出)。
debug版本方便程序员对程序进行调试,而release版本将很多可以调试的地方优化了(例如:
assert
会在release版本下失效)。
release的大小也比debug大。
-g
选项。sudo yum install -y gdb
gcc -g test.c -o test_g
默认情况下gdb无法对当前发布的版本(默认为release版本)进行调试,要发布debug版本才行。
发布debug版本的文件,使用调试指令进行调试。
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
注意:gdb中如果本次没有输入指令,则默认同上一次的指令相同,直接进行执行(直接enter)。
被访问的时间,原本的规则是每次访问时间都会被改变,但是由于一旦文件被修改,就意味着它被访问了,而它被访问了却不一定被需修改,为了避免修改频率太快,导致资源浪费(访问时间用处也不大),因此是在一段时间里,多次访问才会更新时间。(不一定是最新时间)
文件内容的修改时间(最新时间)
文件属性的修改时间(最新时间),文件内容发生变化会导致文件属性发生修改,文件属性包括文件内容。
看看如下代码
先sleep还是先printf?
根据程序运行的顺序,先printf再sleep。
但是,通过运行我们发现是先sleep了,之后才打印出来了。
说明是先将内容放在缓冲区,sleep后再将缓冲区内容显示在屏幕上。
但是,如果在printf中增加\n,则会及时的显示内容。
因此,我们明白printf的内容是先存放在缓冲区里,等到缓冲区刷新时才会显示到显示器上。
一般而言:
\r换行是指换到下一行
\n回车指回到当前行的最开始
但是在语言层面
\n就是回车换行
显示器面板上有各种像素点,凡是显示到显示器上的都是字符(显示器不认识字符的含义,只是根据用户的要求进行显示一个一个的字符)
代码如下,大家可以自行运行尝试。
注意:
- 用\r回到当前行的最开始,用新的值覆盖旧的值就能实现动态倒计时的效果;
- 因为\r不会主动刷新缓冲区,导致缓冲区的内容无法显示在显示器上,因此每一次都要用fflush函数对缓冲区进行刷新;
- 因为cnt从两位数变为一位数的,因此我们为了将它最初的两位数都可以进行覆盖,要对打印的格式进行控制。
如果需要源码,可以参考该网址(我的gitee):
实现一个进度条源代码
以上就是今天要讲的内容,本文介绍了Linux中的基础开发工具的相关知识。本文作者目前也是正在学习Linux相关的知识,如果文章中的内容有错误或者不严谨的部分,欢迎大家在评论区指出,也欢迎大家在评论区提问、交流。
最后,如果本篇文章对你有所启发的话,希望可以多多支持作者,谢谢大家!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。