文章目录
1、Linux 软件包管理器 yum
Linux 下安装软件的方案
1、源代码安装
2、rpm包安装(前两种不推荐)
3、包管理器进行安装—yum/apt
1.1什么是软件包
(1)在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序.
(2)但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的软件包, 直接进行安装.
(3)软件包和软件包管理器, 就好比 “App” 和 “应用商店” 这样的关系.
(4)yum(Yellow dog Updater, Modified)是Linux下非常常用的一种包管理器. 主要应用在Fedora, RedHat, Centos等发行版上.
1.2 关于 rzsz
这个工具用于 windows 机器和远端的 Linux 机器通过 XShell 传输文件.
安装完毕之后可以通过拖拽的方式将文件上传过去
1.3 注意事项
关于 yum 的所有操作必须保证主机(虚拟机)网络畅通!!!
可以通过 ping 指令验证
ping www.baidu.com
1.4 查看软件包
通过 yum list 命令可以罗列出当前一共有哪些软件包. 由于包的数目可能非常之多, 这里我们需要使用 grep 命令只筛选出我们关注的包. 例如:
yum list | grep lrzsz
结果如下
lrzsz.x86_64 0.12.20-36.el7 @base
注意事项:
(1)软件包名称: 主版本号.次版本号.源程序发行号-软件包的发行号.主机平台.cpu架构.
(2)“x86_64” 后缀表示64位系统的安装包, “i686” 后缀表示32位系统安装包. 选择包时要和系统匹配.
(3)“el7” 表示操作系统发行版的版本. “el7” 表示的是 centos7/redhat7. “el6” 表示 centos6/redhat6.
(4)最后一列, base 表示的是 “软件源” 的名称, 类似于 “小米应用商店”, “华为应用商店” 这样的概念.
1.5 如何安装软件
通过 yum, 我们可以通过很简单的一条命令完成 gcc 的安装
sudo yum install lrzsz
yum 会自动找到都有哪些软件包需要下载, 这时候敲 “y” 确认安装.
出现 “complete” 字样, 说明安装完成.
注意事项:
(1)安装软件时由于需要向系统目录中写入内容, 一般需要 sudo 或者切到 root 账户下才能完成.
(2)yum安装软件只能一个装完了再装另一个. 正在yum安装一个软件的过程中, 如果再尝试用yum安装另外一个软件, yum会报错.
(3)如果 yum 报错, 请自行百度.
Linux下的软件,root安装了,其他用户能看嘛?能
linux一般而言,软件只要安装一次,都能用!other的身份
1.6 如何卸载软件
sudo yum remove lrzsz
查看安装卸载
sudo
yum list | grep xxx
yum install [-y] xxxx
yum remove [-y] xxxx
2.Linux开发工具
(1)IDE例子
3. Linux编辑器-vim使用
vi/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面。例如语法加亮,可视化操作不仅可以在终端运行,也可以运行于x window、 mac os、windows。多模式的编辑器。
3.1 vim的基本概念
我们讲解vim的三种模式(其实有好多模式,目前掌握这3种即可),分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:
(1)正常/普通/命令模式(Normal mode)
控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode
(2)插入模式(Insert mode)
只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。该模式是我们后面用的最频繁的编辑模式。
(3)末行模式(last line mode)
文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 在命令模式下,shift+: 即可进入该模式。要查看你的所有模式:打开vim,底行模式直接输入
:help vim-modes
意义:
1、默认打开是命令模式
2、命令模式是vim的核心和精华。
我这里一共有12种模式:six BASIC modes和six ADDITIONAL modes.
vim的使用:
3.2. vim的基本操作
(1)进入vim,在系统提示符号输入vim及文件名称后,就进入vim全屏幕编辑画面
$ vim test.c
不过有一点要特别注意,就是你进入vim之后,是处于[正常模式],你要切换到[插入模式]才能够输入文字。
(2)[正常模式]切换至[插入模式]
输入a
输入i
输入o
(3)[插入模式]切换至[正常模式]
目前处于[插入模式],就只能一直输入文字,如果发现输错了字,想用光标键往回移动,将该字删除,可以先按一下「ESC」键转到[正常模式]再删除文字。当然,也可以直接删除。
(4)[正常模式]切换至[末行模式]
「shift + ;」, 其实就是输入「:」
(5)退出vim及保存文件,在[正常模式]下,按一下「:」冒号键进入「Last line mode」,例如:
: w (保存当前文件)
: wq (输入「wq」,存盘并退出vim)
: q! (输入q!,不存盘强制退出vim)
3.3. vim正常模式命令集
(a)插入模式
(1)按「i」切换进入插入模式「insert mode」,按“i”进入插入模式后是从光标当前位置开始输入文件;
(2)按「a」进入插入模式后,是从目前光标所在位置的下一个位置开始输入文字;
(3)按「o」进入插入模式后,是插入新的一行,从行首开始输入文字。
(b)从插入模式切换为命令模式
按「ESC」键。
(c)移动光标
vim可以直接用键盘上的光标来上下左右移动,但正规的vim是用小写英文字母**「h」、「j」(jump下)、「k」(king上)、「l」,分别控制光标左、下、上、右移一格**
why(有方向为啥用字母啊)?
按「G」:移动到文章的最后
按「 $ 」:移动到光标所在行的“行尾(shift+4)”
按「^」:移动到光标所在行的“行首(shift+6)”
按「w」:光标跳到下个字的开头
按「e」:光标跳到下个字的字尾
按「b」:光标回到上个字的开头
按「#l」:光标移到该行的第#个位置,如:5l,56l
按[gg]:进入到文本开始
可以加数字定位到任意行
n+gg
按[shift+g]:进入文本末端
可以加数字定位到任意行
n+shift+g
按「ctrl」+「b」:屏幕往“后”移动一页
按「ctrl」+「f」:屏幕往“前”移动一页
按「ctrl」+「u」:屏幕往“后”移动半页
按「ctrl」+「d」:屏幕往“前”移动半页
(d)删除文字
「x」:每按一次,删除光标所在位置的一个字符
「#x」:例如,「6x」表示删除光标所在位置的“后面(包含自己在内)”6个字符
「X」:大写的X,每按一次,删除光标所在位置的“前面”一个字符
「#X」:例如,「20X」表示删除光标所在位置的“前面”20个字符
「dd」:删除光标所在行
「#dd」:从光标所在行开始删除#行
(e)复制
「yw」:将光标所在之处到字尾的字符复制到缓冲区中。
「#yw」:复制#个字到缓冲区
「yy」:复制光标所在行到缓冲区。
「#yy」:例如,「6yy」表示拷贝从光标所在的该行“往下数”6行文字。
「p」:将缓冲区内的字符贴到光标所在位置。注意:所有与“y”有关的复制命令都必须与“p”配合才能完成复制与粘贴功能。
(f)替换
「r」:替换光标所在处的字符。 shift+r 替换就相当于R.
「R」:替换光标所到之处的字符,直到按下「ESC」键为止。
(g)撤销上一次操作
只要不退vim就可以一直撤销。
「u」:如果您误执行一个命令,可以马上按下「u」,回到上一个操作。按多次“u”可以执行多次回复。
「ctrl + r」: 撤销的恢复
(h)更改
「cw」:更改光标所在处的字到字尾处
「c#w」:例如,「c3w」表示更改3个字
(i)跳至指定的行
「ctrl」+「g」列出光标所在行的行号。
「#G」:例如,「15G」,表示移动光标至文章的第15行行首。
shift+“~”快速自动转换大小写字母
shif+zz 保存并退出vim
3.4. vim末行模式命令集
在使用末行模式之前,请记住先按「ESC」键确定您已经处于正常模式,再按「:」冒号即可进入末行模式。
(1)列出行号
「set nu」: 输入「set nu」后,会在文件中的每一行前面列出行号
(2)跳到文件中的某一行
「#」:「#」号表示一个数字,在冒号后输入一个数字,再按回车键就会跳到该行了,如输入数字15,再回车,就会跳到文章的第15行。
(3)查找字符
「/关键字」: 先按「/」键,再输入您想寻找的字符,如果第一次找的关键字不是您想要的,可以一直按「n」会往后寻找到您要的关键字为止。
「?关键字」:先按「?」键,再输入您想寻找的字符,如果第一次找的关键字不是您想要的,可以一直
按「n」会往前寻找到您要的关键字为止。
问题:/ 和 ?查找有和区别?操作实验一下
(4)保存文件
「w」: 在冒号输入字母「w」就可以将文件保存起来
(5)离开vim
「q」:按「q」就是退出,如果无法离开vim,可以在「q」后跟一个「!」强制离开vim。
「wq」:一般建议离开时,搭配「w」一起使用,这样在退出的时候还可以保存文件。
/!command/vs other
分屏:ctrl+ww
3.5. vim操作总结
(1)三种模式
正常模式
插入模式
底行模式
我们一共有12种总模式。
vim操作
打开,关闭,查看,查询,插入,删除,替换,撤销,复制等等操作
3.5.1补充更加实用的命令操作!
(1)批量化编辑(命令模式)
1、批量化注释:ctrl+v->hjkl->shift+i->//->Esc
2、批量化去注释:ctrl+v ->hjkl->d
(2)底行模式(替换)
:%s/要替换的目标/要替换的内容/g
(3)命令行定位
vim code.c +11
(4)!g
3.6.1 简单vim配置
3.6.2配置文件的位置
(1)在目录 /etc/ 下面,有个名为vimrc的文件,这是系统中公共的vim配置文件,对所有用户都有效。
(2)而在每个用户的主目录下,都可以自己建立私有的配置文件,命名为:“.vimrc”。例如,/root目录下,
通常已经存在一个.vimrc文件,如果不存在,则创建之。
(3)切换用户成为自己执行 su ,进入自己的主工作目录,执行 cd ~
(4)打开自己目录下的.vimrc文件,执行 vim .vimrc
3.6.3常用配置选项,用来测试
设置语法高亮: syntax on
显示行号: set nu
设置缩进的空格数为4: set shiftwidth=4
3.6.4使用插件
要配置好看的vim,原生的配置可能功能不全,可以选择安装插件来完善配置,保证用户是你要配置的用户,接下来:
(1)安装TagList插件,下载taglist_xx.zip ,解压完成,将解压出来的doc的内容放到~/.vim/doc, 将解压出来的plugin下的内容拷贝到~/.vim/plugin
(2)在~/.vimrc 中添加: let Tlist_Show_One_File=1 let Tlist_Exit_OnlyWindow=1 let
Tlist_Use_Right_Window=1
(3)安装文件浏览器和窗口管理器插件: WinManager
(4)下载winmanager.zip,2.X版本以上的
(5)解压winmanager.zip,将解压出来的doc的内容放到~/.vim/doc, 将解压出来的plugin下的内容拷贝到~/.vim/plugin
(6)在~/.vimrc 中添加 let g:winManagerWindowLayout=‘FileExplorer|TagList nmap wm :WMToggle
(7)然后重启vim,打开~/XXX.c或~/XXX.cpp, 在normal状态下输入"wm", 你将看到上图的效果。更具体移步:点我, 其他手册,请执行 vimtutor 命令。
一键配置
curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh
按照上述就能安装成功。
3.7 参考资料
4、Linux编译器-gcc/g++使用
gcc/g++编译选择上,gcc用来编译c,g++编译c/c++.
4.1. 背景知识
- 预处理(进行宏替换)
- 编译(生成汇编)
- 汇编(生成机器可识别代码)
- 连接(生成可执行文件或库文件)
4.2. gcc如何完成
格式 gcc [选项] 要编译的文件 [选项] [目标文件]
4.2.1预处理(进行宏替换)
预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
预处理指令是以#号开头的代码行。
实例: gcc –E hello.c –o hello.i
选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序
理解头文件展开
把要需要关于头文件内容展开拷贝到源文件中。
4.2.2编译(生成汇编)
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查
无误后,gcc 把代码翻译成汇编语言。
用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
实例: gcc –S hello.i –o hello.s
-S开始进行程序翻译,编译做完,形成汇编,就停下来。
4.2.3汇编(生成机器可识别代码)
汇编阶段是把编译阶段生成的“.s”文件转成目标文件
读者在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了
实例: gcc –c hello.s –o hello.o
-c
开始进行程序的翻译
汇编完成就停下来
code.o
a、可重定位目标文件二进制文件
b、无法执行
4.2.4连接(生成可执行文件或库文件)
我们的.o库文件进行连接->可执行
在成功编译之后,就进入了链接阶段。
实例: gcc hello.o –o hello
程序翻译过程“ESc”
.iso
4.2.5在这里涉及到一个重要的概念:函数库
我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而
没有定义函数的实现,那么,是在哪里实“printf”函数的呢?
最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到
系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函
数“printf”了,而这也就是链接的作用
4.2.6函数库一般分为静态库和动态库两种。
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也
就不再需要库文件了。其后缀名一般为“.a”
动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时
链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态
库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。 gcc
hello.o –o hello
gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证
理论:
动态库是共享的,所以不能丢失,一旦丢失,所有依赖动态库的程序都会运行出错
静态链接:把我们的库方法实现,直接拷贝到我们的可执行程序中
静态优点:不依赖库
缺点:浪费空间(磁盘和内存,网络等)
4.2.7gcc选项
-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
-S 编译到汇编语言不进行汇编和链接
-c 编译到目标代码
-o 文件输出到 文件
-static 此选项对生成的文件采用静态链接
-g 生成调试信息。GNU 调试器可利用该信息。
-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
-O0
-O1
-O2
-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-w 不生成任何警告信息。
-Wall 生成所有警告信息。
4.2.8gcc选项记忆
esc,iso例子
5Linux调试器-gdb使用
5.1. 背景
程序的发布方式有两种,debug模式和release模式
Linux gcc/g++出来的二进制程序,默认是release模式
要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项
5.2. 开始使用
gdb binFile 退出: ctrl + d 或 quit 调试命令:
list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
list/l 函数名:列出某个函数的源代码。
r或run:运行程序。
n 或 next:单条执行。
s或step:进入函数调用
break(b) 行号:在某一行设置断点
break 函数名:在某个函数开头设置断点
info break :查看断点信息。
finish:执行到当前函数返回,然后挺下来等待命令
print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数
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
5.3. 理解
和windows IDE对应例子
6.Linux项目自动化构建工具-make/Makefile
6.1背景
会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一
种在工程方面的编译方法。
make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
6.2理解
核心思想:
具体语法:
a、
make会自顶而下扫描makefile文件,默认形成第一个目标文件
如果想指定形成,make targetname
伪目标?
所依赖的方法:总是被执行
伪目标(如下图)
why?make只能编译一次?提高编译效率。
如何决定要不要重新编译?
对比源文件和可执行文件的修改时间。对比的就是M时间。
b、makefile推导原则
(1)、make会进行依赖关系的推导,直到依赖文件是存在的。
(2)、依赖方法不断入栈,推导完毕,出栈执行方法。
c、更加具有通用型的makefile
makefile,c语言运行通用摸板
1 BIN=mytest
2 #SRC=$(shell ls *.c)
3 SRC=$(wildcard *.c)
4 OBJ=$(SRC:.c=.o)
5 CC=gcc
6 RM=rm -f
7
8
9 $(BIN):$(OBJ)
10 @$(CC) $^ -o $@
11 @echo "链接 $^ 成 $@"
12 %.o:%.c
13 @$(CC) -c $<
14 @echo "编译... $< 成 $@"
15
16 .PHONY:clean
17 clean:
18 @$(RM) $(OBJ) $(BIN)
19
20 .PHONY:test
21 test:
22 @echo $(BIN)
23 @echo $(SRC)
24 @echo $(OBJ)
6.3 依赖方法
gcc hello.* -option hello.* ,就是与之对应的依赖关系
6.4原理
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只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
6.5 项目清理
工程是需要被清理的。
像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编
译。
但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的。
可以将我们的 hello 目标文件声明成伪目标,测试一下
7.Linux第一个小程序-进度条
7.1 \r&&\n
回车概念
换行概念
老式打字机的例子
7.2行缓冲区概念
什么现象?
#include <stdio.h>
int main()
{
printf("hello Makefile!\n");
sleep(3);
return 0;
}
什么现象?
#include <stdio.h>
int main()
{
printf("hello Makefile!");
sleep(3);
return 0;
}
什么现象???
#include <stdio.h>
int main()
{
printf("hello Makefile!");
fflush(stdout);
sleep(3);
return 0;
}
倒计时代码段
1 #include<stdio.h>
2 #include<unistd.h>
3 int main()
4 {
7 int cnt = 10;
8 while(cnt>=0)
9 {
10 printf("%-2d\r",cnt);
11 fflush(stdout);
12 cnt--;
13 sleep(1);
14
15 }
16 printf("\n");
20 // sleep(2);
21 return 0;
22 }
7.3进度条代码
process.h
1 #pragma once //防止头文件重复包含
2
3 #include<stdio.h>
4 //v1
5 void process();
6
7 //v2
8 void FlushProcess(const char*,double total,double current);
process.c
#include"process.h"
2 #include<string.h>
3 #include<unistd.h>
4 #define SIZE 101
5 #define STYLE '#'
6 //v2:根据进度,动态刷新一次进度条
7 void FlushProcess(const char *tips,double total,double current)
8 {
9 const char*lable ="|/-\\";
10 int len = strlen(lable);
11 static int index = 0;
12 char buffer[SIZE];
13 memset(buffer,0,sizeof(buffer));
14 double rate = current*100/total;
15 int num = (int) rate;//计算#的个数
16
17 int i = 0;
18 for(;i<num;i++)
19 {
20 buffer[i] = STYLE;
21 }
22 printf("[%s......][%-100s][%.1lf%%][%c]\r",tips,buffer,rate,lable[index++]);
23 fflush(stdout);
24 index %= len;
25 if(num>=100) printf("\n");
}
27
28 //v1:展示进度条基本功能
29
30
31 void process()
32 {
33 int rate = 0 ;
34 char buffer[SIZE];
35 memset(buffer,0,sizeof(buffer));//把buffer里面的数全部清成0
36 const char *lable = "|/-\\";
37 int len = strlen(lable);
38 v1:展示进度条基本功能
39 while(rate<=100)
40 {
41 printf("[%-100s][%d%%][%c]\r",buffer,rate,lable[rate%len]);
42 fflush(stdout);//刷新才能立即打印
43 buffer[rate] = STYLE;
44 rate++;
45 usleep(20000);
46 }
47 printf("\n");
48 }
main.c
#include"process.h"
2 #include<unistd.h>
3 #include<time.h>
4 #include<stdlib.h>
5 //完成一个下载任务
6 // void(*call)(double,double);//函数指针类型
7 typedef void(*call_t)(char*,double,double);
8
9 //
10 double total =1024.0;//下载总量
11 //double speed = 1.0;//网速
12 double speed[] = {1.0,0.5,0.3,0.2,0.01,0.001};
13 //回调函数
14 void download(double total,call_t cb)
15 {
16 srand(time(NULL));
17 double current = 0.0;//当前下载量
18 while(current <= total)
19 {
20 //更新进度
21 // FlushProcess(total,current);
W> 22 cb("下载中",total,current);//进行回调
23 if(current>=total)break;
24 //下载代码
25 int random = rand()%6;
usleep(5000);
27 current += speed[random];
28 if(current>=total) current = total;
29
30 }
31 }
32
33
34 void uploadload(double total,call_t cb)
35 {
36 srand(time(NULL));
37 double current = 0.0;//当前下载量
38 while(current <= total)
39 {
40 //更新进度
41 // FlushProcess(total,current);
W> 42 cb("上传中",total,current);//进行回调
43 if(current>=total)break;
44 //下载代码
45 int random = rand()%6;
46 usleep(5000);
47 current += speed[random];
48 if(current>=total) current = total;
50 }
51 }
52
53 int main()
54 {
E> 55 download(1024.0,FlushProcess);
56 printf("download 1024.0MB done\n");
E> 57 download(512.0,FlushProcess);
58 printf("download 512.0MB done\n");
E> 59 download(256.0,FlushProcess);
60 printf("download 256.0MB done\n");
E> 61 download(64.0,FlushProcess);
62 printf("download 64.0MB done\n");
E> 63 download(32.0,FlushProcess);
64 printf("download 32.0MB done\n");
E> 65 download(8.0,FlushProcess);
66 printf("download 8.0MB done\n");
E> 67 uploadload(500.0,FlushProcess);
68 return 0;
69 }
8.使用 git 命令行
git:版本控制器。
如何理解版本控制->Git&&gitee||github
存档保存新建。
版本控制why?
随时进行回退。
git历史:git是开源的。
8.1安装 git
yum install git
8.2在 Github 创建项目
9.使用 Github 创建项目
9.1注册账号
这个比较简单, 参考着官网提示即可. 需要进行邮箱校验.
9.2创建项目
- 登陆成功后, 进入个人主页, 点击左下方的 New repository 按钮新建项目
2. 然后跳转到的新页面中输入项目名称(注意, 名称不能重复, 系统会自动校验. 校验过程可能会花费几秒钟). 校验完毕后, 点击下方的 Create repository 按钮确认创建
- 在创建好的项目页面中复制项目的链接, 以备接下来进行下载
9.3下载项目到本地
创建好一个放置代码的目录.
git clone [url]
这里的 url 就是刚刚建立好的 项目 的链接.
9.4三板斧第一招: git add
将代码放到刚才下载好的目录中
git add [文件名]
将需要用 git 管理的文件告知 git
9.5三板斧第二招: git commit
提交改动到本地
git commit .
最后的 “.” 表示当前目录
提交的时候应该注明提交日志, 描述改动的详细内容
9.6三板斧第三招: git push
: git push
同步到远端服务器上
git push
需要填入用户名密码. 同步成功后, 刷新 Github 页面就能看到代码改动了
配置免密码提交
配置免密码提交
补充
(1)git提交的时候,只会提交变化的部分。
git log(查看日志)。
git status (查看状态)
(2)首次使用报错的解决
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
(3)git版本管理,只进行管理源文件
(4)gitignore:需要忽略的特定后置文件列表。
(5)远端仓库拉取到本地,linux再提交,冲突了,怎么解决?
git pull
远端仓库,相比较与任何人,都是最新的。
为什么要冲突?
提醒本地用户,你要和远端仓库进行同步了!
知识点
1、操作系统生态问题
社区活跃度,文档完不完善等
2、什么OS是好的OS?
生态好。
3、重新理解Centos vs Ubnutu vs kaili …
4、为什么有人愿意免费提供社区软件?
维护社区,利益驱使等。
5、“生态”来源于开源,开源的本质是一种商业模式。
6、我的服务器怎么知道,去哪里找软件包?
Linux机器上,有对应的给yum/apt提供的配置文件!url或者ip地址。
云服务器:内置的配置文件已经是国内的。
虚拟机:安装软件,更新yum源。
镜像源:
软件包依赖的问题
rpm包
yum源
扩展软件源
[root@hcss-ecs-298b ~]# cd /etc/yum.repos.d/
[root@hcss-ecs-298b yum.repos.d]# yum install -y epel-release
切换软件源
本质:就是更改配置文件.
centos 7 切换yum源到163,操作清单:
1、下载163源的repo文件:
使用wget命令从指定URL下载适用于CentOS 7的163源repo文件,例如:
wget http://mirrors.163.com/.help/CentOS7-Base-163.repo
2、备份当前yum源配置:
备份原有的CentOS-Base.repo文件,以便在需要时恢复:
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
替换为163源的repo文件:
将下载的CentOS7-Base-163.repo文件移动到yum源配置目录,并重命名为CentOS-Base.repo:
mv CentOS7-Base-163.repo /etc/yum.repos.d/CentOS-Base.repo
3、清理yum缓存并生成新缓存:
执行以下命令以确保新源生效:
验证yum源切换:
yum clean all
yum makecache
4、使用yum repolist命令检查当前启用的yum源,确认163源已正确配置。
可选:安装EPEL源:
如果需要额外的软件包,可以安装EPEL源:
yum install epel-release
5、恢复原始配置的步骤:
如需恢复原始yum源,只需将备份文件重命名回原文件即可:
mv /etc/yum.repos.d/CentOS-Base.repo.bak /etc/yum.repos.d/CentOS-Base.repo
以上步骤涵盖了从下载到验证的完整流程,并提供了恢复原始配置的方法,确保用户能够安全地进行yum源切换。
6、为什么要编译,为什么要汇编,编译器自举,理解条件编译。
减少语言开发成本
1、纸带打孔的方式进行编程。(二进制编程)
2、汇编语言
编译器诞生
先有编译器,第一代编译器用什么语言写的,二进制编译器(用来编译汇编语言所写的软件);编译器自己是不是软件?是的;汇编语言,重构编译器。汇编所写的编译器就不需要二进制编译器;这整个过程就叫做编译器自举。
3、面向对象,面向过程的语言c
用到编译器自举。
条件编译:根据对应宏进行裁剪。
裁剪作用?免费版,校园版,社区版,专业版
代码版本维护。
7、动静态库和静态链接–操作部分
库:动态库,静态库
Linux: 动态库(libXXXX.so) 静态库 (libXXXX.a)
Windows: XXXX.dll XXXX.lib
文件名就是剩下的部分。
注意:
问题出现在使用 gcc 编译时,链接器 (ld) 报错提示无法找到 -lc,即标准 C 库的静态版本。以下是问题的详细分析和解决方法:
sudo yum groupinstall "Development Tools"
sudo yum install glibc-static
gcc默认形成的可执行程序是动态链接的。
gcc-static:进行动态链接。
Linux一般只会存在动态库(绿色的那个)。
安装动静态库(c语言和c++)
sudo yum install glibc-static libstdc++static -y
补充
解决sudo
vim文件修改(如下图)
7gdb/cgdb使用
Linux下我们编译好的代码,无法直接调试!
gcc/g++默认的工作模式是release模式!
-g选项,让最后形成的可执行程序,添加调试信息—debug模式!
2、程序要调试,必须是debug模式!编译的要加-g选项,gdb携带调试信息的exe。
7.1 快速认识gdb
gdb bin
quit
7.2 gdb命令的学习
7.21 常见使用
命令 作⽤ 样例
list/l 显⽰源代码,从上次位置开始,每次列出
10⾏
list/l 10
list/l 函数名 列出指定函数的源代码 list/l main
list/l ⽂件名:⾏号 列出指定⽂件的源代码 list/l mycmd.c:1
r/run 从程序开始连续执⾏ run
n/next 单步执⾏,不进⼊函数内部 next
s/step 单步执⾏,进⼊函数内部 step
break/b [⽂件名:]⾏号 在指定⾏号设置断点 break 10
break test.c:10
break/b 函数名 在函数开头设置断点 break main
info break/b 查看当前所有断点的信息 info break
finish 执⾏到当前函数返回,然后停⽌ finish
print/p 表达式 打印表达式的值 print start+end
p 变量 打印指定变量的值 p x
set var 变量=值 修改变量的值 set var i=10
continue/c 从当前位置开始连续执⾏程序 continue
delete/d
breakpoints
删除所有断点 delete breakpoints
delete/d
breakpoints n
删除序号为n的断点 delete breakpoints 1
disable breakpoints 禁⽤所有断点 disable breakpoints
enable breakpoints 启⽤所有断点 enable breakpoints
info/i breakpoints 查看当前设置的断点列表 info breakpoints
display 变量名 跟踪显⽰指定变量的值(每次停⽌时) display x
undisplay 编号 取消对指定编号的变量的跟踪显⽰ undisplay 1
until X⾏号 执⾏到指定⾏号 until 20
backtrace/bt 查看当前执⾏栈的各级函数调⽤及参数 backtrace
info/i locals 查看当前栈帧的局部变量值 info locals
quit 退出GDB调试器 quit
7.3 解决一下gdb难用问题,三个debug技巧
cgdb
安装cgdb
推荐安装cgdb:
• Ubuntu: sudo apt-get install -y cgdb
• Centos: sudo yum install -y cgdb
打断点:b行号
d断点编号
info b 查看断点。
r ,运行程序
gdb不退出,断点编号,依次递增
n 逐过程
s 逐语句,gdb会自动记录最新的一条语句。
7.4调试的本质:
1、找到问题
找到命令的本质,是把代码进行块级别划分,以块为单位进行快速定位区域。
finish->确定问题是否在函数内
until ->局部区域快速执行。
2、查看代码上下文
7.5 watch
(gdb) l main
return result;
}
int main()
{
int start = 1;
int end = 100;
printf("I will begin\n");
int n = Sum(start, end);
(gdb) b 20
Breakpoint 1 at 0x11c3: file mycmd.c, line 20.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000000011c3 in main at mycmd.c:20
(gdb) r
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:20
20 int n = Sum(start, end);
(gdb) s
Sum (s=32767, e=-7136) at mycmd.c:5
5 {
(gdb) n
6 int result = 0;
(gdb) watch result
Hardware watchpoint 2: result
(gdb) c
Continuing.
Hardware watchpoint 2: result
Old value = -6896
New value = 0
Sum (s=1, e=100) at mycmd.c:7
7 for(int i = s; i <= e; i++)
(gdb) c
Continuing.
Hardware watchpoint 2: result
Old value = 0
New value = 1
Sum (s=1, e=100) at mycmd.c:7
7 for(int i = s; i <= e; i++)
(gdb) c
Continuing.
Hardware watchpoint 2: result
Old value = 1
New value = 3
Sum (s=1, e=100) at mycmd.c:7
7 for(int i = s; i <= e; i++)
(gdb) c
Continuing.
Hardware watchpoint 2: result
Old value = 3
New value = 6
Sum (s=1, e=100) at mycmd.c:7
7 for(int i = s; i <= e; i++)
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
2 hw watchpoint keep y result
breakpoint already hit 4 times
(gdb) d 2
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
(gdb) finish
Run till exit from #0 Sum (s=1, e=100) at mycmd.c:7
0x00005555555551d2 in main () at mycmd.c:20
20 int n = Sum(start, end);
Value returned is $1 = 5050
7.6 set var确定问题原因
更改⼀下标志位,假设我们想得到 ±result
// mycmd.c
#include <stdio.h>
int flag = 0; // 故意错误
//int flag = -1;
//int flag = 1;
int Sum(int s, int e)
{
int result = 0;
for(int i = s; i <= e; i++)
{
result += i;
}
return result*flag;
}
int main()
{
int start = 1;
int end = 100;
printf("I will begin\n");
int n = Sum(start, end);
printf("running done, result is: [%d-%d]=%d\n", start, end, n);
return 0;
}
(gdb) l main
return result*flag;
}
int main()
{
int start = 1;
int end = 100;
printf("I will begin\n");
int n = Sum(start, end);
(gdb) b 24
Breakpoint 1 at 0x11ca: file mycmd.c, line 24.
(gdb) r
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:24
24 int n = Sum(start, end);
(gdb) n
25 printf("running done, result is: [%d-%d]=%d\n", start, end,
n);
(gdb) n
running done, result is: [1-100]=0 # 这⾥结果为什么是0?
26 return 0;
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:24
24 int n = Sum(start, end);
(gdb) s
Sum (s=32767, e=-7136) at mycmd.c:9
9 {
(gdb) n
10 int result = 0;
(gdb) n
11 for(int i = s; i <= e; i++)
(gdb)
13 result += i;
(gdb)
11 for(int i = s; i <= e; i++)
(gdb)
13 result += i;
(gdb) until 14
Sum (s=1, e=100) at mycmd.c:16
16 return result*flag;
(gdb) p result
$1 = 5050
(gdb) p flag
$2 = 0
(gdb) set var flag=1 # 更改flag的值,确认是否是它的原因
(gdb) p flag
$3 = 1
(gdb) n
17 }
(gdb) n
main () at mycmd.c:25
25 printf("running done, result is: [%d-%d]=%d\n", start, end,
n);
(gdb) n
running done, result is: [1-100]=5050 # 是它的原因
return 0;
7.7 条件断点
添加条件断点
(gdb) l main
11
12 return result;
13 }
14
15 int main()
16 {
17 int start = 1;
18 int end = 100;
19 printf("I will begin\n");
20 int n = Sum(start, end);
(gdb) b 20
Breakpoint 1 at 0x11c3: file mycmd.c, line 20.
(gdb) r
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:20
20 int n = Sum(start, end);
(gdb) s
Sum (s=32767, e=-7136) at mycmd.c:5
5 {
(gdb) n
6 int result = 0;
(gdb) n
7 for(int i = s; i <= e; i++)
(gdb) n
9 result += i;
(gdb) display i
1: i = 1
(gdb) n
7 for(int i = s; i <= e; i++)
1: i = 1
(gdb) n
9 result += i;
1: i = 2
(gdb) n
7 for(int i = s; i <= e; i++)
1: i = 2
(gdb) n
9 result += i;
1: i = 3
(gdb)
7 for(int i = s; i <= e; i++)
1: i = 3
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
(gdb) b 9 if i == 30 # 9是⾏号,表⽰新增断点的位置
Breakpoint 2 at 0x555555555186: file mycmd.c, line 9.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9
stop only if i == 30
(gdb) finish
Run till exit from #0 Sum (s=1, e=100) at mycmd.c:7
Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9
9 result += i;
1: i = 30
(gdb) finish
Run till exit from #0 Sum (s=1, e=100) at mycmd.c:9
0x00005555555551d2 in main () at mycmd.c:20
20 int n = Sum(start, end);
Value returned is $1 = 5050
给已经存在的端点新增条件
(gdb) l main
11
12 return result;
13 }
14
15 int main()
16 {
17 int start = 1;
18 int end = 100;
19 printf("I will begin\n");
20 int n = Sum(start, end);
(gdb) b 20
Breakpoint 1 at 0x11c3: file mycmd.c, line 20.
(gdb) r
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:20
20 int n = Sum(start, end);
(gdb) s
Sum (s=32767, e=-7136) at mycmd.c:5
5 {
(gdb) n
6 int result = 0;
(gdb) n
7 for(int i = s; i <= e; i++)
(gdb) n
9 result += i;
(gdb)
7 for(int i = s; i <= e; i++)
(gdb)
9 result += i;
(gdb)
7 for(int i = s; i <= e; i++)
(gdb)
9 result += i;
(gdb)
7 for(int i = s; i <= e; i++)
(gdb) b 9 # 我们在第9⾏新增⼀个断点,⽤来开始测试
Breakpoint 2 at 0x555555555186: file mycmd.c, line 9.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9
(gdb) n
Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9
9 result += i;
(gdb) n
7 for(int i = s; i <= e; i++)
(gdb) n
Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9
9 result += i;
(gdb) condition 2 i==30 #给2号断点,新增条件i==30
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9
stop only if i==30
breakpoint already hit 2 times
(gdb) n
7 for(int i = s; i <= e; i++)
(gdb) n
9 result += i;
(gdb) c
Continuing.
Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9
9 result += i;
(gdb) p i
$1 = 30
(gdb) p result
$2 = 435
注意:
• 条件断点添加常⻅两种⽅式:1. 新增 2. 给已有断点追加
• 注意两者的语法有区别,不要写错了。
• 新增: b ⾏号/⽂件名:⾏号/函数名 if i == 30(条件)
• 给已有断点追加:condition 2 i==30, 其中2是已有断点编号,没有if
cgdb分屏操作ESC进入代码屏, i 回到GDP的屏
总结
以上就是Linux环境基础开发工具使用(沉淀中)的全部内容了,喜欢博主写的内容可以一键三连!!