源码安装(不简单)
rpm 安装(不简单)
类似于 windows 下安装包
需要使用 rpm 命令
yum安装(简单)
不用编译源码
不用解决软件的依赖关系
sudo yum install sl
sudo yum remove sl
sudo 是给普通用户管理员权限, 在第一次使用时需要将该用户加进去
如果我要知道我要安装什么软件,用yum 可以很简单
我们需要安装别人的软件:
sudo 用户切换到root 用户
编辑sudo文件的写权限 chmod +w /etc/sudoer
编辑sudoers文件:vim /etc/sudoers
找到 root ALL=(ALL) ALL 在后面加上下面的语句
用户名 ALL=(ALL) NOPASSWD: ALL
退出 Esc --> :wq
参数的说明:
youuser ALL=(ALL) ALL 允许用户youuser执行sudo命令(需要输入密码)
%youuser ALL=(ALL) ALL 允许用户组youuser里面的用户执行sudo命令(需要输入密码)
youuser ALL=(ALL) NOPASSWD: ALL 允许用户youuser执行sudo命令,并且在执行的时候不输入密码
%youuser ALL=(ALL) NOPASSWD: AL 允许用户组youuser里面的用户执行sudo命令,并且在执行的时候不输入密码
链接
rzsz这个工具用于windows 机器和远端的 Linux 机器通过XShell 传输文件
安装完毕之后可以通过拖拽的方式将文件上传上去
使用grep指令筛选出需要的包
yum list | grep lrzsz

安装
sudo yum installl lrzsz.x86_64
随便打开一个文件夹,将桌面的文件拖进去
卸载
sudo yum remove lrzsz.x86_64
IDE 及使用Linux 下的编辑器 — vim
vim 有多种模式,接下来,我们将主要介绍三种模式。分别是命令模式( command mode )、插入模式( Insert mode )、底行模式( last line mode )
正常/普通/命令模式( Normal mode )
控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入 Insert mode 下,或者到 last line mode
插入模式( Insert mode )
只有在 Insert mode 下,才可以做文字输入,按 ESC 键可回到命令行模式。
末行模式( last line mode )
文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 在命令模式下,shift+: 即可进入该模式。要查看你的所有模式:打开vim,底行模式直接输入 :help vim-modes
我这里一共有12种模式: six BASIC modes 和 six ADDITIONAL modes
进入vim,在系统提示符号输入vim及文件名称后,就进入vim全屏幕编辑画面:
vim test.c
我们进入vim时是处于正常模式,你要切换到插入模式才能够输入文字
正常模式切换至插入模式
插入模式切换至正常模式
目前处于插入模式,就只能一直输入文字
如果发现输错了字,想用光标键往回移动,将该字删除,可以先按一下ESC键转到正常模式再删除文字。
当然,也可以直接删除。
正常模式切换至末行模式
shift +;, 其实就是输入:
退出vim及保存文件,在正常模式下,按一下**:冒号键进入Last line mode**,例如:
: w (保存当前文件): wq (输入wq,存盘并退出vim): q! (输入q!,不存盘强制退出vim)插入模式
从插入模式切换为命令模式
移动光标
G] :移动到文章的最后$]: 移动到光标所在行的 行尾^]: 移动到光标所在行的 行首w]: 光标跳到下个字母的开头e]: 光标跳到下个字母的字尾b]: 光标回到上个字母的开头#l]: 光标从当前位置,向右移动 # 号个距离gg]: 进入到文本的开始shift + g]: 进入文本末端ctrl + b]:屏幕向" 后 "移动一页ctrl + f]:屏幕向" 前 "移动一页ctrl + u]:屏幕向" 后 "移动一页Ctrl + d]:屏幕向" 前 "移动一页删除文字
x]: 每按一次,删除光标所在位置的一个字符#x]: 例如,[6x ]表示删除光标所在位置的“后面(包含自己在内)”6个字符X]: 大写的X,每按一次,删除光标所在位置的“前面”一个字符#X]: 例如,[20X ]表示删除光标所在位置的“前面”20 个字符dd]: 删除光标所在行#dd]:从光标所在行开始删除#行复制
按[yw]: 将光标所在之处到字尾的字符复制到缓冲区中
按[#yw]:复制#个字到缓冲区
按[yy]: 复制光标所在行到缓冲区
按[#yy]:例如,[6yy ]表示拷贝从光标所在的该行"往下数"6行文字
按[p]: 将缓冲区内的字符贴到光标所在位置。
注意:所有与"y"有关的复制命令都必须与"p"配合才能完成复制与粘贴功能。
替换
r]: 替换光标所在处的字符R]:替换光标所到之处的字符,直到按下[ESC ]键为止撤销上一次操作
u]:如果您误执行一个命令,可以马上按下[u ],回到上一个操作。按多次“u”可以执行多次回复。Ctrl + r]:撤销的恢复更改
cw]: 更改光标所在处的字到字尾处c#w]:例如,[c3w]表示更改3个字跳至指定的行
ctrl+g]:列出光标所在行的行号。#G]:例如,[15G],表示移动光标至文章的第15行行首。在使用末行模式之前,请记住先按ESC键确定您已经处于正常模式,再按**:**冒号即可进入末行模式。
列出行号
[set nu]: 输入[set nu]后,会在文件中的每一行前面列出行号
跳到文件中的某一行
[#]:[#]号表示一个数字,在冒号后输入一个数字,再按回车键就会跳到该行了,如输入数字15,再回车,就会跳到文章的第15行。
查找字符
保存文件
w]: 在冒号输入字母[w]就可以将文件保存起来离开vim
q]:按[q]就是退出,如果无法离开vim,可以在[q]后跟一个[!]强制离开vim。wq]:一般建议离开时,搭配[w]一起使用,这样在退出的时候还可以保存文件。/etc/ 下面,有个名为vimrc的文件,这是系统中公共的vim配置文件,对所有用户都有效。.vimrc。例如,/root目录下,通常已经存在一个.vimrc文件,如果不存在,则创建之。su ,进入自己的主工作目录,执行 cd ~.vimrc文件,执行 vim .vimrcsyntax onset nuset shiftwidth=4gcc / g++ 的使用程序(文本) —> 机器语言(二进制)
计算机为什么只认识二进制?
组成计算机的各种组件,只能认识二进制
gcc [选项] 要编译的文件 [选项] [目标文件]gcc –E hello.c –o hello.i-E,该选项的作用是让gcc在预处理结束后停止编译过程。-o 是指目标文件,.i 文件为已经过预处理的C原始程序。
g++ -E test.cpp -o test.i-E从现在开始给我进行程序的翻译,当预处理完成,就停下来。
左边是预处理之后的结果,右边是原代码
系统中头文件的路径:
/usr/include/
编译器内部都必须通过一定的方式,知道你所包含的头文件所在路径。
gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。-S 选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。gcc –S hello.i –o hello.s把
cpp语言翻译为汇编语言
g++ -S test.i -o test.s-S从现在开始进行程序的翻译,当我们编译完成之后,就停下来!
.s 文件转成目标文件-c 就可看到汇编代码已转化为 .o 的二进制目标代码了gcc –c hello.s –o hello.o将汇编语言翻译为二进制文件,可重定位二进制文件。
.o/.obj
g++ -c test.s -o test.o-c从现在开始进行程序的翻译,当我们汇编结束之后,就停下来!二进制查看工具:
od test.o
所有包含头文件的操作,本质是想用头文件声明的方法
如何和目标方法产生链接
gcc hello.o –o hello
c标准库
ls /lib64/libc*
/lib64/libc-2.17.soc库printf的实现在里面连接:将我们写的代码 和 库的代码连接起来
g++ test.o -o mytest连接自己的程序和库
ldd mytest查看mytest所依赖的库
C程序中,并没有定义 printf 的函数实现,且在预编译中包含的 stdio.h 中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实 printf 函数的呢?libc.so.6的库文件中去了,在没有特别指定时, gcc 会到系统默认的搜索路径/usr/lib下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数 printf 了,而这也就是链接的作用.a.so ,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。gcc hello.o –o hellogcc默认生成的二进制程序,是动态链接的,这点可以通过file命令验证。头文件:给我们提供了可以使用的方法,所有的开发环境,具有语法提示,本质是通过头文件帮助我们搜索
库文件:给我们提供了可以使用的方法的实现,以供链接,形成我们自己的可执行程序
动态库:
Linux(.so)windows(.dll)动态链接 链接的时候把库关联起来,优点:大家共享一个库,可以节省资源
缺点:一旦库缺失,会导致几乎所有的程序失效
静态库:
Linux(.a)windows(.lib)静态链接 将库中的代码直接拷贝到自己的可执行程序中优点:不依赖任何库,程序可以独立执行
缺点:浪费资源
默认情况下形成的可执行程序就是静态链接的。
如果想要静态的:
g++ test.cpp -o mytest -static需要手动安装静态库:
sudo yum install -y glibc-static sudo yum install -y libstdc++-static
- 1
- 2
gcc 选项-O0、-O1、-O2、-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高-w 不生成任何警告信息。-Wall 生成所有警告信息。gdb的使用debug 模式和release 模式Linux gcc/g++出来的二进制程序,默认是release 模式gdb调试,必须在源代码生成二进制程序的时候, 加上-g选项
gcc test.c -o test -std=c99默认形成的可执行程序无法调试,
release模式
gcc test.c -o test -std=c99 -g-g是debug版本
readelf -S test分析ELF文件格式
readelf -S test | grep debug查找调试信息
开始:gdb binFile
退出: ctrl + d 或 quite
调试命令:
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
l 0从第一行开始查看代码,按回车之后会执行上次代码,然后把逐次把剩余的代码看完。
b n在第n行打一个断点
d num删除编号为num的断点
info b查看所打的断点
r开始跑程序,到达断点停车
p res查看res的值
p &res查看res的地址
s逐语句执行
n逐过程执行(把所有函数调用当成一个语句,一下就运行完)
display res一直显示res这个变量的值(常显示)
undisplay res取消常显示
until num跳转到第num行,中间代码一次性跑完
bt调用堆栈
finish执行完成一个函数就停下来
make / Makefile
有自动形成
makefile的工具。
项目构建
项目结构:
.h .c . cpp 先编译哪一个什么是make/ makefile ?
makefile 文件中内容
单文件
mytest:mytest.c
gcc mytest.c -o mytest
.PHONY:clean
clean:
rm -f mytest
mytest:mytest.c #依赖关系 目标文件: 依赖文件列表
gcc mytest.c -o mytest # 依赖方法, 必须以Tab 开头
# 使用 make 指令执行 依赖方法
.PHONY:clean # 总是被执行, 只要使用 make clean 指令, 依赖方法一定会执行
clean: # 无论目标文件是否最新 总是会执行
rm -f mytest
makefile 中自顶向下形成
makefile 是如何识别我的 exe/bin 是新的还是旧的呢?
stat mytest能够查看文件的属性Linux 下的文件有三种时间:`Access`(读取或进去的时间) `Modify`(内容发生改变) `Change`(属性发生改变) 文件 = 内容 + 属性 内容变了属性也会变 访问时间:访问文件的内容是一个特别高频的事件。当累计上一定的次数之后,才会更改。调整策略被调改
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 通过对比源文件 和 可执行程序的
Modify时间 可执行在源文件的后面
多文件
hello:main.o test.o
gcc -o hello main.o test.o
main.o:main.c
gcc -c main.c
test.o:test.c
gcc -c test.c -o test.o
.PHONY:clean
clean:
rm -f *.o hello
缓冲区
#include
#include
int main()
{
printf("hello world\n");
sleep(2);
return 0;
}
会先打印出来
hello world然后再睡眠两秒钟
#include
#include
int main()
{
printf("hello world");
sleep(2);
return 0;
}
会先打印出来
hello world然后再睡眠两秒钟但现实的效果上是先睡眠两秒 再现实
hello world原因:代码是从上到下运行的。在缓冲区中。
立马将内存中的空间显示出来 – 刷新策略(缓存区满了、遇到换行符、程序结束)
不想用
\n把数据显示出来
#include
#include
int main()
{
printf("hello world");
fflush(stdout); // 用来刷新
sleep(2);
return 0;
}
回车与换行符
换行:换到下一行
回车:将光标回到当前行的最开始
回车 和 换行 通常称为回车
倒计时:
#include
#include
int main()
{
int cnt = 9;
while (cnt) {
printf("%d\r", cnt--);
fflsh(stdout);
sleep(1);
}
return 0;
}
#include
#include
#include
const int NUM = 101;
void process()
{
char bar[NUM];
memset(bar, '\0', sizeof(bar));
const char* label = "|/-\\";
int cnt = 0;
while (cnt <= 100) {
printf("\033[46;34m%-100s\033[0m[%d%%][%c]\r", bar, cnt, label[cnt % 4]);
fflush(stdout);
bar[cnt++] = '#';
usleep(20000);
}
printf("\n");
}
int main()
{
process();
return 0;
}
int cnt = 9;
while (cnt) {
printf(“%d\r”, cnt–);
fflsh(stdout);
sleep(1);
}
return 0;
}
### 进度条
```cpp
#include
#include
#include
const int NUM = 101;
void process()
{
char bar[NUM];
memset(bar, '\0', sizeof(bar));
const char* label = "|/-\\";
int cnt = 0;
while (cnt <= 100) {
printf("\033[46;34m%-100s\033[0m[%d%%][%c]\r", bar, cnt, label[cnt % 4]);
fflush(stdout);
bar[cnt++] = '#';
usleep(20000);
}
printf("\n");
}
int main()
{
process();
return 0;
}